# Filesystem The `fs/` namespace is the stdlib's whole-file and path layer: read, write, list, inspect, and watch files and directories. It is compiled into every runtime and needs no import. Paths whose leading segment names a VFS mount route to that mount's driver instead of the native filesystem — see VFS. For line-oriented I/O on an open file (rather than whole-file reads and writes), use the bare channel functions `open`, `puts`, `gets`, and `close` from I/O. Read/stat/list calls also resolve import/package paths: when a path whose leading segment(s) name an import mount (e.g. `deft/help/manual/01-Language/...`) doesn't exist as a literal path, it is resolved through the same probe `import`/`import/resolve` use — including package-root assets such as `manual/` and `docs/` that sit beside `src/`. The same logical path therefore works from any working directory, in dev checkouts and installed package trees; an existing native path always wins. ## Functions ### Reading and writing | Function | Purpose | |---|---| | `fs/read "path"` | Read a file's contents as a string: `%Ok{:value "..."}`; `%Err` on failure | | `fs/write "path" "content"` | Write a string to a file, creating or truncating it (`%Ok{:value true}` / `%Err`) | | `fs/append "path" "content"` | Append a string to a file (`%Ok{:value true}` / `%Err`) | | `fs/read-lines "path"` | Read a file as a vector of lines (`%Ok`; a final newline is not an extra line) | | `fs/write-lines "path" @{...}` | Write a vector of lines, one newline per line (`%Ok{:value true}` / `%Err`) | | `fs/copy "from" "to"` | Copy a file; `%Ok{:value true}` on success (read + write, so it composes across VFS mounts) | | `fs/rename "from" "to"` | Rename or move a file (`%Ok{:value true}` / `%Err`; same mount) | | `fs/remove "path"` | Remove a file or empty directory (`%Ok{:value true}` / `%Err`) | | `fs/link "target" "link-path"` | Create a symlink at `link-path` pointing to `target` (`%Ok{:value true}` / `%Err`; native only) | | `fs/mkdir "path"` | Create a directory and any missing parents; idempotent (`%Ok{:value true}` / `%Err`) | ### Metadata and predicates | Function | Purpose | |---|---| | `fs/exists? "path"` | True when the path exists | | `fs/file? "path"` | True when the path exists and is not a directory | | `fs/dir? "path"` | True when the path is a directory | | `fs/absolute? "path"` | True for absolute paths and mount-anchored paths | | `fs/stat "path"` | `%Ok` with `%{ :size N :is-dir bool :modified ms }`; mtime in epoch milliseconds | | `fs/list "path"` | `%Ok` with a vector of `%{ :name str :is-dir bool :kind str }` entries | | `fs/readdir "path"` | `%Ok` with a vector of entry names (strings) only | | `fs/glob "path" "pattern" ?opts` | Files whose basename matches `*`/`?`, as `%Ok` with `%{ :path dir :file name }` maps; `%{ :recurse true }` (or `--recurse`) walks subdirectories | ### Path helpers | Function | Purpose | |---|---| | `fs/join "a" "b" ...` | Join components with `/` | | `fs/abs "path"` | Absolute path; mount-anchored paths pass through unchanged | | `fs/dir "path"` | Directory portion (`"."` when there is none) | | `fs/base "path"` | Filename portion | | `fs/ext "path"` | Extension including the dot (`.txt`), empty when there is none | ### Host and scratch paths | Function | Purpose | |---|---| | `fs/tempdir` | System temp directory (`$TMPDIR`, else `/tmp`) | | `fs/home` | Home directory (`$HOME`; `nil` when unset) | | `fs/tmp-dir` | Per-process scratch directory `/tmp/deft-<pid>/`, created on first call | | `fs/tmp-path ?file` | The scratch directory, or a path inside it when given a filename | | `fs/local-path "sub" "file"` | Conventional `.deft/local/<sub>/<file>` path; does not create directories | | `fs/local-dir "sub"` | `.deft/local/<sub>`, created (with parents) if needed; idempotent | ### Watching | Function | Purpose | |---|---| | `fs/watch "path" callback` | Watch a file or directory (recursive) and return `%Ok` with a numeric watch-id | | `fs/unwatch $id` | Cancel a watch; true when a watch was removed | Notes: - The whole-file verbs return `%Ok{:value ...}` on success and `%Err{:message}` on failure: data verbs wrap their payload (`%Ok{:value "..."}`, `%Ok{:value list}`), mutation verbs wrap `true` (`%Ok{:value true}`). Unwrap with `ok!`, `unwrap`, `match`, or `err?` — or call the predicates (`fs/exists?`, `fs/file?`, `fs/dir?`, `fs/absolute?`), which return booleans instead. - `fs/watch` invokes its callback with a flag keyword — `:created`, `:modified`, or `:removed` — and the changed path. Handlers fire only while the event loop pumps (`vwait`, `update`, servers), the same contract as `[after]` and network callbacks. - VFS routing applies to the whole-file verbs and metadata calls; `fs/watch`, `fs/link`, and recursive `fs/glob` are local-only. The host-path helpers (`fs/tempdir`, `fs/home`, `fs/tmp-dir`, `fs/tmp-path`, `fs/local-path`, `fs/local-dir`) stay host-local by design. Details in VFS. ## Examples ### Write and read a file
def path "/tmp/deft-notes/notes.txt"
fs/mkdir [fs/dir $path]
fs/write $path "first line\nsecond line\n"

echo "contents:" [unwrap [fs/read $path]]
each [unwrap [fs/read-lines $path]] {|line| echo "line:" $line }
### List a directory
each [unwrap [fs/readdir "packages/help/docs"]] {|name| echo $name }

for entry in [unwrap [fs/list "packages/help/docs"]] {
    echo $entry~name "dir?" $entry~is-dir "kind" $entry~kind
}
`fs/readdir` gives names only; `fs/list` gives `%{ :name :is-dir :kind }` maps. `fs/glob` searches by basename and can recurse:
def hits [unwrap [fs/glob "packages/help/manual" "*.md" %{ :recurse true }]]
each $hits {|hit| echo [fs/join $hit~path $hit~file] }
### Build paths with fs/join
set root [fs/tempdir]
set out  [fs/join $root "deft-exports" "report.txt"]
echo "dir:" [fs/dir $out] "base:" [fs/base $out] "ext:" [fs/ext $out]
# dir: /tmp/deft-exports  base: report.txt  ext: .txt
### Watch a directory
def wid [unwrap [fs/watch "www" {|flag file| echo $flag $file }]]
# ... the event loop runs (vwait / sleep / server) ...
[fs/unwatch $wid]
## See Also - I/O — channels and the bare `open` / `puts` / `gets` / `close` verbs - VFS — mount routing behind the `fs/` namespace - OS — subprocess and environment helpers - Data Formats — `yaml/load` reads through the filesystem