Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

fs

files, directories, paths, JSON and CSV

Example results generated on 2026-10-08. Ones using now, today or randomness will differ when you run them: press Run on any example to run it in your browser, after editing it if you like.

tables

# ls(dir?), glob(pat) give name, type, size, modified
# glob: * and ? within a name, ** across directories

Functions

functiondescription
read_file(path: str)file contents as a string
write_file(path: str, v: any)replace a file with v as text; a list is one item per line, a table is CSV
append_file(path: str, v: any)add v to the end of a file as text, creating it if needed; a list is one item per line
exists(path: str)whether a file or directory exists
is_dir(path: str)whether path is a directory
ls(dir?: str)a directory’s entries as a table: name, type, size, modified
glob(pat: str)paths matching pat as a table like ls; * and ? match within a name, ** across directories
file_size(path: str)size in bytes, as a quantity
mtime(path: str)when the file was last modified
rm(path: str)delete a file or an empty directory
mv(from: str, to: str)move or rename a file or directory, creating missing folders
cp(from: str, to: str)copy a file, creating missing folders
mkdir(path: str)create a directory and any missing parents
path_join(a: str, b: str, ...)join path pieces with the OS separator
basename(path: str)the last piece of a path, or nil
dirname(path: str)everything before the last piece, or nil
ext(path: str)the extension without its dot, or nil
stem(path: str)the last piece without its extension, or nil
abspath(path: str)path made absolute from the current directory; need not exist
cwd()the current directory
cd(dir?: str)change the current directory, home by default; returns the new one
from_json(s: str)parse JSON: objects become maps, arrays lists
to_json(v: any)v as JSON; values JSON lacks (quantities, fractions, dates) become strings
from_csv(s: str, header?: bool)parse CSV; with a header row (the default) a table, else a list of rows. Numbers become numbers, empty cells nil
to_csv(rows: table|list)CSV text from a table, a list of maps, or a list of lists

read_file

read_file(path: str): file contents as a string

read_file("notes.txt").lines.len
read_file("data.json").from_json

See also: write_file, lines, from_csv

write_file

write_file(path: str, v: any): replace a file with v as text; a list is one item per line, a table is CSV

write_file("out.txt", [1, 2, 3])
write_file("files.csv", ls())

See also: read_file, append_file

append_file

append_file(path: str, v: any): add v to the end of a file as text, creating it if needed; a list is one item per line

append_file("log.txt", ["started {now}"])

See also: write_file

exists

exists(path: str): whether a file or directory exists

exists("Cargo.toml")

See also: is_dir

is_dir

is_dir(path: str): whether path is a directory

is_dir("src")

See also: exists

ls

ls(dir?: str): a directory’s entries as a table: name, type, size, modified

ls()
ls("src").where(|f| f.type == "file").name

See also: glob, sort_by

glob

glob(pat: str): paths matching pat as a table like ls; * and ? match within a name, ** across directories

glob("**/*.rs").size.sum
glob("*.csv").name

See also: ls

file_size

file_size(path: str): size in bytes, as a quantity

file_size("Cargo.lock") to KiB

See also: mtime, human_bytes

mtime

mtime(path: str): when the file was last modified

now - mtime("Cargo.lock") to h

See also: file_size

rm

rm(path: str): delete a file or an empty directory

rm("out.txt")

See also: mv, mkdir

mv

mv(from: str, to: str): move or rename a file or directory, creating missing folders

mv("draft.txt", "final.txt")

See also: cp, rm

cp

cp(from: str, to: str): copy a file, creating missing folders

cp("data.csv", "backup/data.csv")

See also: mv

mkdir

mkdir(path: str): create a directory and any missing parents

mkdir("out/2026/10")

See also: rm

path_join

path_join(a: str, b: str, ...): join path pieces with the OS separator

path_join("a", "b.txt")
# → "a/b.txt"

See also: dirname, basename

basename

basename(path: str): the last piece of a path, or nil

"a/b/c.txt".basename
# → "c.txt"

See also: dirname, stem

dirname

dirname(path: str): everything before the last piece, or nil

"a/b/c.txt".dirname
# → "a/b"

See also: basename

ext

ext(path: str): the extension without its dot, or nil

"a/b.tar.gz".ext
# → "gz"
"README".ext
# → nil

See also: stem

stem

stem(path: str): the last piece without its extension, or nil

"a/b.tar.gz".stem
# → "b.tar"

See also: ext, basename

abspath

abspath(path: str): path made absolute from the current directory; need not exist

abspath("src")

See also: cwd

cwd

cwd(): the current directory

cwd()

See also: abspath, cd

cd

cd(dir?: str): change the current directory, home by default; returns the new one

cd("src")
cd("..")
cd()

See also: cwd

from_json

from_json(s: str): parse JSON: objects become maps, arrays lists

"\{\"a\": [1, 2.5, null]}".from_json
# → {a: [1, 2.5, nil]}

See also: to_json, parse

to_json

to_json(v: any): v as JSON; values JSON lacks (quantities, fractions, dates) become strings

{a: [1, nil], b: 5 km}.to_json
# → "{\"a\":[1,null],\"b\":\"5 km\"}"

See also: from_json

from_csv

from_csv(s: str, header?: bool): parse CSV; with a header row (the default) a table, else a list of rows. Numbers become numbers, empty cells nil

"name,n\nx,1".from_csv
# → table([{name: "x", n: 1}])
"1,2\n3,4".from_csv(false)
# → [[1, 2], [3, 4]]

See also: to_csv, table

to_csv

to_csv(rows: table|list): CSV text from a table, a list of maps, or a list of lists

[{a: 1, b: "x,y"}].to_csv
# → a,b
# → 1,"x,y"
# → 
[[1, 2], [3, 4]].to_csv
# → 1,2
# → 3,4
# → 

See also: from_csv

More examples

fs

# JSON to a value
"\{\"a\": [1, 2]}".from_json.a.sum
# → 3
# CSV to a table
"name,n\nx,1\ny,2".from_csv.n.sum
# → 3
# path pieces
["a/b.tar.gz".stem, "a/b.tar.gz".ext]
# → ["b.tar", "gz"]