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

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.

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, with is_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 the Directory is used

Returns

  • the Directory; an error when path cannot 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 create
  • mode — 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 at path, 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 parents
  • mode — the permission bits of path on 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 at path or 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"));
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 to
  • link — where to create the link

Returns

  • an Ok result once the link exists; an error with is_already_exists() when something is already at link, 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() when path is 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() when path does not exist (unlike rm -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, path is empty), is_permission_denied(), or on POSIX is_not_a_directory() when path now 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 DirectoryIterator positioned 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”)