Module fs/walker
Recursive directory traversal.
Example
{ walk, WalkEntry } :: import "std/fs/walker";
main :: (fn(io : Io, exn : Exception) -> unit)({
entries := io.await(walk(Path.new(`/tmp`), io), { io, exn });
i := usize(0);
while runtime((i < entries.len())), {
e := entries(i);
println(e.path);
i = (i + usize(1));
};
});
The walk is EAGER and iterative: walk_with drains the whole tree into
one ArrayList(WalkEntry) before its future resolves, using an explicit
stack rather than recursion, so depth costs heap and not C stack. The root
itself is never an entry — only what is inside it. Order is the
filesystem's, further shuffled by the stack (the last subdirectory found
is the first descended), so nothing here is sorted; sort if you need
determinism.
Stability
unstable — Rust's walkdir is a lazy Iterator<Item = Result<DirEntry>>
and this is a materialised list, which decides two things a caller
cannot work around: walk over a large tree allocates the entire tree
(there is no "stop after the first match" — glob below pays exactly
that cost), and ONE unreadable subdirectory throws out of the whole walk
instead of surfacing as one failed item. follow_symlinks is also
disabled outright on Windows
(issues/walker-follow-symlinks-windows-unsupported.md). Freezing
follows a lazy cursor with per-entry errors and Windows symlink descent,
not a release count.
Types
Entry returned by the directory walker.
Fields
| Name | Type | Description |
|---|---|---|
path | Path | Full path, built as walk-root + every intervening directory name +
|
name | String | The entry's own name, with no directory part. |
depth | u32 | How deep below the walk root this entry sits: |
file_type | FileType | The entry's kind, WITHOUT following a final symlink — a link is always
|
Options controlling directory walk behavior.
Fields
| Name | Type | Description |
|---|---|---|
max_depth | Option(u32) | Deepest |
follow_symlinks | bool | Descend THROUGH directory symlinks as well as reporting them. Off by
default, and ignored entirely on Windows (see the module header).
Following is cycle-guarded by canonicalising each followed target and
entering it at most once, so a link pointing at an ancestor terminates
instead of recursing forever — but it costs a |
include_dirs | bool | Report directories as entries of their own, not just their contents.
Directories are DESCENDED either way; this only decides whether they
appear in the result. |
pattern | Option(String) | When set, only entries whose path RELATIVE TO THE WALK ROOT matches
this glob (std/glob semantics; |
impl(WalkOptions, ...)
defaults : (WalkOptions) fn() -> WalkOptionsUnlimited depth, symlinks reported but not followed, directories
included, no pattern — what walk uses.
Returns: WalkOptions
Functions
Walk the tree under root with explicit options, returning every entry
found — the general form behind walk and glob.
Async: awaited on the single-threaded event loop, and it throws IoExn
as soon as any directory in the tree cannot be read (including root
itself), discarding the entries collected so far. A tree the caller has
only partial access to therefore needs read_dir per level rather than
this.
Symlink handling is deferred by design: a directory's symlinks are
collected while its entries are scanned and resolved in a second pass
over that same directory, because the stat + canonicalize the follow
decision needs are awaits, and an await that deep inside the scan loop
trips the async state machine
(issues/async-nested-cond-await-duplicate-while-labels.md).
Parameters
| Name | Type | Notes |
|---|---|---|
root | Path | |
options | WalkOptions | |
io | Io |
walk_with taking a NUL-terminated C string as the root, for callers
already holding one from a C API. Identical otherwise: the bytes are
copied into a Path immediately. An undecodable or unterminated pointer
yields an EMPTY path rather than an error (Path.from_cstr), which then
throws when the walk tries to read it.
Parameters
| Name | Type | Notes |
|---|---|---|
root | *u8 | |
options | WalkOptions | |
io | Io |
Expand a glob pattern against the filesystem — the Python/Node meaning:
walk from the pattern's static prefix and return every matching path
(files, dirs and symlinks alike; ** crosses directories). Throws the
walker's IoExn when the static base directory cannot be read.
Parameters
| Name | Type | Notes | Description |
|---|---|---|---|
pattern | String | When set, only entries whose path RELATIVE TO THE WALK ROOT matches
this glob (std/glob semantics; | |
io | Io |
Recursively remove a directory and everything under it
(std::fs::remove_dir_all). Does NOT follow symlinks — a symlinked
directory is removed as a LINK, its target untouched.
Lives HERE rather than in std/fs/dir because the implementation is the
walker (collect the whole tree, delete deepest-first) and fs/walker
imports fs/dir — the reverse import would be a cycle. This is the same
implementation the compiler ran in production as a private helper
(src/fetch.yo) before it moved into std.
Parameters
| Name | Type | Notes | Description |
|---|---|---|---|
path | Path | Full path, built as walk-root + every intervening directory name +
| |
io | Io |
Returns: Impl(Future(unit, IoExn))
remove_dir_all (str path variant).
Parameters
| Name | Type | Notes | Description |
|---|---|---|---|
path | str | Full path, built as walk-root + every intervening directory name +
| |
io | Io |
Returns: Impl(Future(unit, IoExn))