std/fs
| Function | Result |
|---|---|
path_join(a, b) |
a/b |
path_dir(path), path_base(path) |
src/lib and text.cz for src/lib/text.cz |
path_ext(path), path_stem(path) |
.cz and text for src/text.cz |
read_lines(path) |
the lines of a file as a Result[str[]] |
split_lines(text) |
the lines of text with LF or CRLF line ends |
write_lines(path, lines) |
replaces a file with lines |
walk(dir) |
every file below a directory, sorted |
The built-ins cover the rest: reading and writing whole files as text or
bytes, appending to them, and writing them atomically (read_bytes,
append_text, write_atomic, ...), and exists, is_dir, make_dir,
list_dir, delete_file, rename_file, current_dir, change_dir,
temp_dir, and temp_file. See
program input and output.
Open files
open_file(path, mode) opens a file to read and write it in parts, and
gives a File, which with closes:
import "std/fs"
with log = open_file("events.log", "a")? do
file_write_text(log, "started\n")?
end
File input = open_file("data.bin", "r")?
file_seek(input, 16, SeekFrom.START)?
bytes header = file_read(input, 8)?
close_file(input)?| Mode | Opens the file to |
|---|---|
"r" |
read |
"w" |
write, replacing it or creating it |
"a" |
add to its end, creating it if needed |
"r+" |
read and write, keeping it |
"w+" |
read and write, replacing it |
"x" |
write a new file, failing with kind "exists" when one is there |
| Function | Result |
|---|---|
file_read(f, n) |
up to n bytes, empty at the end of the file |
file_read_line(f) |
SOME of the next line without its LF or CRLF, or NONE at the end |
file_write(f, data), file_write_text(f, text) |
writes bytes or text and gives how many bytes |
file_seek(f, offset, from) |
moves to offset from SeekFrom.START, CURRENT, or END, and gives the new position |
file_position(f) |
the position |
file_truncate(f, size) |
makes the file size bytes long |
file_flush(f), file_sync(f) |
hands what was written to the system, or makes sure it reached the disk |
close_file(f) |
closes the file; again does nothing |
lock_file(f, exclusive) |
locks the whole file against other processes, waiting while another holds it |
try_lock_file(f, exclusive) |
the same, giving OK(false) instead of waiting |
unlock_file(f) |
releases the lock |
Each returns a Result; the ones with nothing else to give return
OK(true). Files are binary: nothing is changed in what is read or
written. Reading and writing can follow each other on a file opened for
both. An exclusive lock is for one writer; shared locks let several readers
hold the file at once. A File is a
Reader and a Writer, so it
works with functions written for any source or destination of bytes. Using a
closed file stops the program.
Information, permissions, and links
file_info(path) tells what a file is, as a FileInfo:
| Field | Value |
|---|---|
kind |
FileKind.FILE, DIRECTORY, LINK, or OTHER |
size |
the size in bytes; 0 for a directory |
modified_ms, accessed_ms |
when the file was last changed and read, in milliseconds since 1970-01-01 UTC |
created_ms |
SOME of when it was made, where the system keeps it: Windows, macOS, and FreeBSD |
permissions |
the POSIX permission bits, such as 0o644; on Windows, 0o444 for a read-only file and 0o666 otherwise |
owner, group |
the POSIX user and group numbers; -1 on Windows |
hidden |
whether the name starts with ., or on Windows whether the file is marked hidden |
link_target |
for a link, SOME of what it points to |
A link is described itself rather than followed. These change files and links:
| Function | Result |
|---|---|
set_permissions(path, bits) |
sets the permissions, as in set_permissions("run.sh", 0o755); on Windows only whether the owner may write counts |
set_modified_time(path, ms) |
sets when the file was last changed |
make_link(target, path) |
a symbolic link at path to target, which need not exist; Windows lets a program make one in developer mode or as an administrator |
make_hard_link(existing, path) |
another name for the same file |
read_link(path) |
what a link points to, as it was written; an ERROR of kind "invalid" for a file that is not a link |
real_path(path) |
the absolute path, with every link followed and no . or .. |
Each returns a Result whose error says what the system reported.
Directories
| Function | Result |
|---|---|
remove_dir(path) |
removes an empty directory |
remove_tree(path) |
removes a file, or a directory with everything in it; links are removed, not followed |
copy_file(from, target) |
copies a file with its permissions and modified time, and gives how many bytes |
copy_tree(from, target) |
copies a file or a whole directory, links as links, and gives how many files |
move_path(from, target) |
moves a file or a directory, also to another file system, where it copies and then removes |
list_dir_info(path) |
the entries of a directory, sorted, as DirEntry values with name, path, and info |
home_dir(), config_dir(), data_dir(), cache_dir(), documents_dir(), desktop_dir() |
the user's directories |
Each returns a Result. The user's directories follow each system:
~/.config, ~/.local/share, and ~/.cache on Linux and the BSDs (or the
XDG_ variables that move them, and user-dirs.dirs for the documents and
the desktop), ~/Library/Application Support and ~/Library/Caches on
macOS, and the roaming and local AppData folders on Windows.
walk_dir(root) goes through everything below a directory one entry at a
time, reading each directory only when it gets there, so it can stop early
on a large tree. Each directory's entries come in order of name, and those
of a subdirectory right after it:
Walker w = walk_dir("src")
w.max_depth = 3 // 1 is the entries of src alone; -1, the default, has no limit
while true do
match next_entry(w)? do
when SOME(entry) then
if entry.name == "build" then
skip_dir(w) // leaves out what is inside
else if path_ext(entry.name) == ".cz" then
print(entry.path, entry.info.size)
end
when NONE then
break
end
endA link to a directory is given as a link and not gone into, unless
follow_links is set; then each directory is gone into once, so a link
that leads back up does not loop.
Large files and the trash
map_file(path) gives the bytes of a file through the system's memory map
of it instead of reading it all: the system brings in the parts a program
looks at, so a program can take slices of a file of gigabytes cheaply. The
map stays until the program ends, and the file must not change while it is
mapped.
trash(path) moves a file or a directory to the system's trash, from where
the user can bring it back: the Recycle Bin on Windows, the Trash on macOS,
and on Linux and the BSDs the trash of the freedesktop.org specification
that file managers share. There, a file on another file system than the
home directory cannot go to the trash, which is an ERROR of kind
"cross_device". Both return a Result.