Directory
Source: runtime/io/directory.pep
DirEntry
struct DirEntry
One entry of a directory listing, as Directory.entries() returns it.
The kind flags come from the listing itself and describe the entry
without following symlinks. On POSIX a symlink has is_symlink set and
is_file and is_directory clear; on Windows a symlink or junction to a
directory has both is_directory and is_symlink set. Entries that are none of
these (a FIFO, socket or device on POSIX) have all three flags clear. Call
metadata() for the details of what the entry points to.
Example
import io;
var list = io.Directory.open(io.Path("src")).value().entries().value();
ulong i = 0;
while (i < list.count) {
if (list[i].is_file) {
print(list[i].Name);
}
i = i + 1;
}
Fields
path
Path path
The entry’s full path: the listed directory’s path joined with
name (relative when the directory’s path was relative).
name
String name
The entry’s own file name, without any directory part.
file_type
FileType file_type
The kind of the entry, without following symlinks: Symlink for a
symlink (on Windows, any reparse point, even one to a directory),
Other for anything that is not a file, directory or symlink.
is_file
bool is_file
Whether the entry is a regular file (never true for a symlink).
is_directory
bool is_directory
Whether the entry is a directory. On POSIX never true for a symlink; on Windows also true for a symlink or junction to a directory.
is_symlink
bool is_symlink
Whether the entry is a symlink (on Windows, any reparse point, junctions included), which is not followed.
Constructor
DirEntry()
construct()
Creates an empty entry: empty path and name, all kind flags
false and file_type Other. Entries are normally obtained from
Directory.entries().
Methods
metadata
metadata(): IoResult<Metadata>
Returns the metadata of the entry, following symlinks, exactly like
Path.metadata() on the entry’s path. The file system is queried
again now, so the result reflects any change since the listing was
read.
Returns
- the entry’s
Metadata(of the target, for a symlink); an error when it cannot be stat’ed, withis_not_found()when the entry was removed since the listing or is a dangling symlink
See also
Path.metadata
Directory
struct Directory
A directory on the file system, identified by its path, together with static functions that create, remove and inspect directories and the process’s current and temporary directories.
A Directory holds no operating-system handle: open only checks that
the path is a directory, and each call to entries() reads the listing
afresh.
Example
import io;
var dir = io.Directory.temp().join("scratch").join("logs");
if (io.Directory.create_all(dir).is_ok()) {
var d = io.Directory.open(dir).value();
var count = d.entries().value().count;
io.Directory.remove_all(io.Directory.temp().join("scratch"));
}
Fields
path
Path path
The directory’s path, as given to open.
Constructor
Directory()
construct()
Creates a Directory with an empty path, which names no directory.
Use Directory.open to get one for an existing directory.
Static methods
open
static open(path: Path): IoResult<Directory>
Checks that path exists and is a directory (following symlinks) and
returns a Directory for it. Nothing is kept open, so the directory
can still be renamed or removed afterwards.
Parameters
path— the directory’s path; a relative path is resolved against the current directory whenever theDirectoryis used
Returns
- the
Directory; an error whenpathcannot be stat’ed (is_not_found()for a missing or empty path,is_permission_denied()) or is not a directory (is_not_a_directory(), message"not a directory")
Example
import io;
var d = io.Directory.open(io.Path("src"));
if (d.is_err() && d.error().is_not_a_directory()) {
print("src is a file");
}
create
static create(path: Path, mode: Mode = 511): IoResult<void>
Creates one directory (mkdir on POSIX, with mode less the
umask; CreateDirectoryW on Windows). Its parent must already exist.
Giving the mode here means the directory never exists with another
one. mode is the POSIX mode_t permission bits (448, octal 700,
for a directory only its owner may use); it is ignored on Windows
and WASI.
Parameters
path— the directory to createmode— the permission bits on POSIX, less the umask; 511 (octal 777) by default
Returns
- an Ok result on success; an error when the directory cannot be created:
is_already_exists()when anything (a file too) is already atpath,is_not_found()when the parent is missing or the path is empty,is_permission_denied()when the parent is not writable
See also
create_all
Example
import io;
var keys = io.Directory.create(io.Path("keys"), mode = 448); # octal 700
create_all
static create_all(path: Path, mode: Mode = 511): IoResult<void>
Creates a directory and any missing parents, like mkdir -p.
Succeeds without doing anything when path is empty or already a
directory (or a symlink to one). Parents are found lexically with
Path.parent(); a relative path is created under the current
directory. It is safe against another process creating the same
directories at the same time.
mode applies to path itself when it is created, as mkdir -p -m
does: missing parents get the default, 511 (octal 777) less the
umask, so the new directory can always be made inside them. An
existing directory keeps its mode. Ignored on Windows and WASI.
Parameters
path— the directory to create, with its parentsmode— the permission bits ofpathon POSIX, less the umask; 511 (octal 777) by default
Returns
- an Ok result on success; an error when a directory cannot be created:
is_already_exists()when a file (not a directory) is atpathor at one of its parents,is_permission_denied(), and so on. Parents created before the failure are left in place
Example
import io;
var r = io.Directory.create_all(io.Path("build").join("out").join("logs"));
symlink
static symlink(target: Path, link: Path): IoResult<void>
Creates a symbolic link at link that points to the directory
target (symlink on POSIX; CreateSymbolicLinkW with
SYMBOLIC_LINK_FLAG_DIRECTORY on Windows). Use File.symlink for a
link to a file: Windows makes the two kinds differently. POSIX makes
the same link either way.
target is stored as given and need not exist; a relative target is
resolved against the directory that holds the link, not the current
directory. On Windows, making a symlink needs Developer Mode or an
administrator, and fails with is_permission_denied() otherwise.
Parameters
target— the directory the link points tolink— where to create the link
Returns
- an Ok result once the link exists; an error with
is_already_exists()when something is already atlink,is_not_found()when its parent is missing or a path is empty,is_permission_denied(), or another platform error
See also
Path.read_link
Example
import io;
io.Directory.symlink(io.Path("releases/1.2"), io.Path("current"));
remove
static remove(path: Path): IoResult<void>
Removes an empty directory (rmdir on POSIX, RemoveDirectoryW on
Windows).
Parameters
path— the directory to remove; it must be empty
Returns
- an Ok result on success; an error when it cannot be removed:
is_directory_not_empty()when it still has entries,is_not_found()when it is missing or the path is empty,is_not_a_directory()whenpathis a file,is_permission_denied()
See also
remove_all
remove_all
static remove_all(path: Path): IoResult<void>
Removes path and, if it is a directory, everything inside it,
recursively. Symlinks are removed, never followed, so nothing outside
the tree is touched. A file or symlink at path itself is simply
removed.
Stops at the first failure, leaving whatever was not yet removed; on
Windows a read-only file inside the tree is such a failure
(is_permission_denied()).
Parameters
path— the file, symlink or directory tree to remove
Returns
- an Ok result on success; an error when something cannot be removed:
is_not_found()whenpathdoes not exist (unlikerm -rf, a missing path is an error) or is empty,is_permission_denied(), and so on
See also
remove
Example
import io;
var tree = io.Directory.temp().join("my-scratch");
var r = io.Directory.remove_all(tree);
if (r.is_err() && !r.error().is_not_found()) {
print(r.error().message);
}
current
static current(): IoResult<Path>
Returns the process’s current directory, against which relative paths
are resolved (getcwd on POSIX, GetCurrentDirectoryW on Windows).
Returns
- the current directory as an absolute path; an error when it cannot be determined, such as
is_not_found()on POSIX when the directory has been removed
See also
set_current
set_current
static set_current(path: Path): IoResult<void>
Changes the process’s current directory (chdir on POSIX,
SetCurrentDirectoryW on Windows). This affects the whole process,
every thread included: relative paths used anywhere afterwards
resolve against the new directory.
Parameters
path— the new current directory; a relative path is resolved against the old one
Returns
- an Ok result on success; an error when the directory cannot be entered:
is_not_found()when it is missing or the path is empty,is_not_a_directory()when it is a file,is_permission_denied()
See also
current
temp
static temp(): Path
Returns the directory for temporary files. It is not created or checked, so it may not exist.
On POSIX it is $TMPDIR with any trailing / removed, or /tmp
when TMPDIR is unset or empty (/data/local/tmp on Android, which
has no /tmp; an app should use its cache directory instead). On Windows it is what
GetTempPathW reports (from TMP, TEMP, USERPROFILE, or the
Windows directory) with its trailing separator removed unless it is
a root, or . if that call fails.
Returns
- the temporary directory’s path, never an error
Example
import io;
var scratch = io.Directory.temp().join("my-tool");
Methods
entries
entries(): IoResult<DirEntry[]>
Reads the directory’s listing now, all at once: every entry except
. and .., in the order the operating system returns them (not
sorted). Uses opendir/readdir on POSIX and
FindFirstFileW/FindNextFileW on Windows. To read the entries one
at a time instead, loop over the Directory itself (see iterate).
Returns
- the entries, possibly none; an error when the directory cannot be read:
is_not_found()when it no longer exists (or, on POSIX,pathis empty),is_permission_denied(), or on POSIXis_not_a_directory()whenpathnow names a file
Example
import io;
var list = io.Directory.open(io.Path(".")).value().entries();
if (list.is_ok()) {
var n = list.value().count;
}
iterate
iterate(): DirectoryIterator
Returns an iterator that reads the directory’s listing one entry at a
time, as for (var entry in dir) does, without building an array.
Each element is an IoResult<DirEntry>. The listing is opened by the
first next(), so a directory that cannot be read yields one error
(the same errors as entries()) and then ends; an error while
reading also ends it. The entries come in the order the operating
system returns them, without . and ... The listing is closed
when it ends, or when the iterator is released, so leaving the loop
early with break or return closes it too.
Returns
- a new
DirectoryIteratorpositioned before the first entry
Example
import io;
var dir = io.Directory.open(io.Path(".")).value();
for (var entry in dir) {
if (entry.is_err()) {
print(entry.error().message);
break;
}
print(entry.value().name);
}
DirectoryIterator
struct DirectoryIterator
The iterator Directory.iterate() returns, and a for loop over a
Directory drives: the directory’s entries, read one at a time, each
as an IoResult<DirEntry>.
It holds the open listing (a DIR* on POSIX, a find handle on Windows)
from the first next() until the listing ends, an error ends it, or the
iterator is released.
See also
Directory.iterate
Example
import io;
var it = io.Directory.open(io.Path(".")).value().iterate();
while (it.next()) {
var entry = it.current();
}
Constructor
DirectoryIterator()
construct(path: Path)
Makes an iterator over the entries of the directory at path. Nothing
is opened until the first next().
Parameters
path— the directory to list
Methods
next
next(): bool
Reads the next entry, opening the listing on the first call.
Once it returns false it keeps returning false.
Returns
- true if there is a current element (an entry, or the error that ends the listing), false once the listing has ended
current
current(): IoResult<DirEntry>
Returns the element the last successful next() moved to.
Returns
- the current entry, or the error that ended the listing
Panics
- if
next()was never called, or already returned false (“DirectoryIterator.current() without an entry”)