% API
Builtins
Path
Path.accessed
Path.accessed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)
Gets the file access time of a file.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file whose access time you want. | - |
| follow_symlinks | Bool |
Whether to follow symbolic links. | yes |
Return: A 64-bit unix epoch timestamp representing when the file or directory was last accessed, or none if no such file or directory exists.
Example:
assert (./file.txt).accessed() == Int64(1704221100)
assert (./not-a-file).accessed() == none
Path.append
Path.append : func(path: Path, text: Text, permissions: Int32 = Int32(0o644) -> Result)
Appends the given text to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to append to. | - |
| text | Text |
The text to append to the file. | - |
| permissions | Int32 |
The permissions to set on the file if it is being created. | Int32(0o644) |
Return: Either Success or Failure(reason).
Example:
(./log.txt).append("extra line\n")!
Path.append_bytes
Path.append_bytes : func(path: Path, bytes: [Byte], permissions: Int32 = Int32(0o644) -> Result)
Appends the given bytes to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to append to. | - |
| bytes | [Byte] |
The bytes to append to the file. | - |
| permissions | Int32 |
The permissions to set on the file if it is being created. | Int32(0o644) |
Return: Either Success or Failure(reason).
Example:
(./log.txt).append_bytes([104, 105])!
Path.base_name
Path.base_name : func(path: Path -> Text)
Returns the base name of the file or directory at the specified path.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file or directory. | - |
Return: The base name of the file or directory.
Example:
assert (./path/to/file.txt).base_name() == "file.txt"
Path.by_line
Path.by_line : func(path: Path -> func(->Text?)?)
Returns an iterator that can be used to iterate over a file one line at a time, or returns none if the file could not be opened.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file. | - |
Return: An iterator that can be used to get lines from a file one at a time or none if the file couldn't be read.
Example:
# Safely handle file not being readable:
if lines := (./file.txt).by_line()
for line in lines
say(line.upper())
else
say("Couldn't read file!")
# Assume the file is readable and error if that's not the case:
for line in (/dev/stdin).by_line()!
say(line.upper())
Path.byte_writer
Path.byte_writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(bytes:[Byte], close:Bool=no -> Result))
Returns a function that can be used to repeatedly write bytes to the same file.
The file writer will keep its file descriptor open after each write (unless the close argument is set to yes). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to write to. | - |
| append | Bool |
If set to yes, writes to the file will append. If set to no, then the first write to the file will overwrite its contents and subsequent calls will append. |
no |
| permissions | Int32 |
The permissions to set on the file if it is created. | Int32(0o644) |
Return: Returns a function that can repeatedly write bytes to the same file. If close is set to yes, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.
Example:
write := (./file.txt).byte_writer()
write("Hello\n".utf8())!
write("world\n".utf8(), close=yes)!
Path.can_execute
Path.can_execute : func(path: Path -> Bool)
Returns whether or not a file can be executed by the current user/group.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to check. | - |
Return: yes if the file or directory exists and the current user has execute permissions, otherwise no.
Example:
assert (/bin/sh).can_execute() == yes
assert (/usr/include/stdlib.h).can_execute() == no
assert (/non/existant/file).can_execute() == no
Path.can_read
Path.can_read : func(path: Path -> Bool)
Returns whether or not a file can be read by the current user/group.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to check. | - |
Return: yes if the file or directory exists and the current user has read permissions, otherwise no.
Example:
assert (/usr/include/stdlib.h).can_read() == yes
assert (/etc/shadow).can_read() == no
assert (/non/existant/file).can_read() == no
Path.can_write
Path.can_write : func(path: Path -> Bool)
Returns whether or not a file can be written by the current user/group.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to check. | - |
Return: yes if the file or directory exists and the current user has write permissions, otherwise no.
Example:
assert (/tmp).can_write() == yes
assert (/etc/passwd).can_write() == no
assert (/non/existant/file).can_write() == no
Path.changed
Path.changed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)
Gets the file change time of a file.
This is the "ctime" of a file, which is not the file creation time.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file whose change time you want. | - |
| follow_symlinks | Bool |
Whether to follow symbolic links. | yes |
Return: A 64-bit unix epoch timestamp representing when the file or directory was last changed, or none if no such file or directory exists.
Example:
assert (./file.txt).changed() == Int64(1704221100)
assert (./not-a-file).changed() == none
Path.child
Path.child : func(path: Path, child: Text -> Path)
Return a path that is a child of another path.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of a directory. | - |
| child | Text |
The name of a child file or directory. | - |
Return: A new path representing the child.
Example:
assert (./directory).child("file.txt") == (./directory/file.txt)
Path.children
Path.children : func(path: Path, include_hidden = no -> [Path])
Returns a list of children (files and directories) within the directory at the specified path. Optionally includes hidden files. Child ordering is not specified.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the directory. | - |
| include_hidden | `` | Whether to include hidden files (those starting with a .). |
no |
Return: A list of paths for the children.
Example:
assert (./directory).children(include_hidden=yes) == [(./directory/.git), (./directory/foo.txt)]
Path.create_directory
Path.create_directory : func(path: Path, permissions = Int32(0o755), recursive = yes -> Result)
Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the directory to create. | - |
| permissions | `` | The permissions to set on the new directory. | Int32(0o755) |
| recursive | `` | If set to yes, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to yes, this function behaves like mkdir -p. |
yes |
Return: Either Success or Failure(reason).
Example:
(./new_directory).create_directory()!
Path.current_dir
Path.current_dir : func(-> Path)
Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.
Return: The absolute path of the current directory.
Example:
assert Path.current_dir() == (/home/user/tomo)
Path.each_child
Path.each_child : func(path: Path, include_hidden = no -> func(->Path?)?)
Returns an iterator over the children (files and directories) within the directory at the specified path. Optionally includes hidden files. Iteration order is not specified.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the directory. | - |
| include_hidden | `` | Whether to include hidden files (those starting with a .). |
no |
Return: An iterator over the children in a directory or none if the path is not a directory or a symlink to a directory.
Example:
for child in (/dir).each_child()
say("Child: $child")
Path.exists
Path.exists : func(path: Path -> Bool)
Checks if a file or directory exists at the specified path.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to check. | - |
Return: True if the file or directory exists, False otherwise.
Example:
assert (/).exists() == yes
Path.expand_home
Path.expand_home : func(path: Path -> Path)
For home-based paths (those starting with ~), expand the path to replace the tilde with and absolute path to the user's $HOME directory.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to expand. | - |
Return: If the path does not start with a ~, then return it unmodified. Otherwise, replace the ~ with an absolute path to the user's home directory.
Example:
# Assume current user is 'user'
assert (~/foo).expand_home() == (/home/user/foo)
# No change
assert (/foo).expand_home() == (/foo)
Path.extension
Path.extension : func(path: Path, full: Bool = yes -> Text)
Returns the file extension of the file at the specified path. Optionally returns the full extension.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file. | - |
| full | Bool |
Whether to return everything after the first . in the base name, or only the last part of the extension. |
yes |
Return: The file extension (not including the leading .) or an empty text if there is no file extension.
Example:
assert (./file.tar.gz).extension() == "tar.gz"
assert (./file.tar.gz).extension(full=no) == "gz"
assert (/foo).extension() == ""
assert (./.git).extension() == ""
Path.files
Path.files : func(path: Path, include_hidden: Bool = no -> [Path])
Returns a list of files within the directory at the specified path. Optionally includes hidden files.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the directory. | - |
| include_hidden | Bool |
Whether to include hidden files (those starting with a .). |
no |
Return: A list of file paths.
Example:
assert (./directory).files(include_hidden=yes) == [(./directory/file1.txt), (./directory/file2.txt)]
Path.glob
Path.glob : func(path: Path -> [Path])
Perform a globbing operation and return a list of matching paths. Some glob specific details:
The paths "." and ".." are not included in any globbing results.
Files or directories that begin with "." will not match
*, but will match.*.Globs do support
{a,b}syntax for matching files that match any of several choices of patterns.The shell-style syntax
**for matching subdirectories is not supported.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the directory which may contain special globbing characters like *, ?, or {...} |
- |
Return: A list of file paths that match the glob.
Example:
# Current directory includes: foo.txt, baz.txt, qux.jpg, .hidden
assert (./*).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]
assert (./*.txt).glob() == [(./foo.txt), (./baz.txt)]
assert (./*.{txt,jpg}).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]
assert (./.*).glob() == [(./.hidden)]
# Globs with no matches return an empty list:
assert (./*.xxx).glob() == []
Path.group
Path.group : func(path: Path, follow_symlinks: Bool = yes -> Text?)
Get the owning group of a file or directory.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path whose owning group to get. | - |
| follow_symlinks | Bool |
Whether to follow symbolic links. | yes |
Return: The name of the group which owns the file or directory, or none if the path does not exist.
Example:
assert (/bin).group() == "root"
assert (/non/existent/file).group() == none
Path.has_extension
Path.has_extension : func(path: Path, extension: Text -> Bool)
Return whether or not a path has a given file extension.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
A path. | - |
| extension | Text |
A file extension (leading . is optional). If empty, the check will test if the file does not have any file extension. |
- |
Return: Whether or not the path has the given extension.
Example:
assert (/foo.txt).has_extension("txt") == yes
assert (/foo.txt).has_extension(".txt") == yes
assert (/foo.tar.gz).has_extension("gz") == yes
assert (/foo.tar.gz).has_extension("zip") == no
Path.is_directory
Path.is_directory : func(path: Path, follow_symlinks = yes -> Bool)
Checks if the path represents a directory. Optionally follows symbolic links.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to check. | - |
| follow_symlinks | `` | Whether to follow symbolic links. | yes |
Return: True if the path is a directory, False otherwise.
Example:
assert (./directory/).is_directory() == yes
assert (./file.txt).is_directory() == no
Path.is_file
Path.is_file : func(path: Path, follow_symlinks = yes -> Bool)
Checks if the path represents a file. Optionally follows symbolic links.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to check. | - |
| follow_symlinks | `` | Whether to follow symbolic links. | yes |
Return: True if the path is a file, False otherwise.
Example:
assert (./file.txt).is_file() == yes
assert (./directory/).is_file() == no
Path.is_socket
Path.is_socket : func(path: Path, follow_symlinks = yes -> Bool)
Checks if the path represents a socket. Optionally follows symbolic links.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to check. | - |
| follow_symlinks | `` | Whether to follow symbolic links. | yes |
Return: True if the path is a socket, False otherwise.
Example:
assert (./socket).is_socket() == yes
Path.is_symlink
Path.is_symlink : func(path: Path -> Bool)
Checks if the path represents a symbolic link.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to check. | - |
Return: True if the path is a symbolic link, False otherwise.
Example:
assert (./link).is_symlink() == yes
Path.lines
Path.lines : func(path: Path -> [Text]?)
Returns a list with the lines of text in a file or returns none if the file could not be opened.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file. | - |
Return: A list of the lines in a file or none if the file couldn't be read.
Example:
lines := (./file.txt).lines()!
Path.matches_glob
Path.matches_glob : func(path: Path, glob: Text -> Bool)
Return whether or not a path matches a given glob.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to check. | - |
| glob | Text |
The glob pattern to check. | - |
Return: Whether or not the path matches the given glob.
Example:
assert (./file.txt).matches_glob("*.txt")
assert (./file.c).matches_glob("*.{c,h}")
Path.modified
Path.modified : func(path: Path, follow_symlinks: Bool = yes -> Int64?)
Gets the file modification time of a file.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file whose modification time you want. | - |
| follow_symlinks | Bool |
Whether to follow symbolic links. | yes |
Return: A 64-bit unix epoch timestamp representing when the file or directory was last modified, or none if no such file or directory exists.
Example:
assert (./file.txt).modified() == Int64(1704221100)
assert (./not-a-file).modified() == none
Path.move
Path.move : func(path: Path, dest: Path, allow_overwriting = no -> Result)
Moves the file or directory from one location to another.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to move. | - |
| dest | Path |
The destination to move the path to. | - |
| allow_overwriting | `` | Whether to permit overwriting the destination if it is an existing file or directory. | no |
Return: Either Success or Failure(reason).
Example:
(./file.txt).move(/tmp/renamed.txt)!
Path.owner
Path.owner : func(path: Path, follow_symlinks: Bool = yes -> Text?)
Get the owning user of a file or directory.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path whose owner to get. | - |
| follow_symlinks | Bool |
Whether to follow symbolic links. | yes |
Return: The name of the user who owns the file or directory, or none if the path does not exist.
Example:
assert (/bin).owner() == "root"
assert (/non/existent/file).owner() == none
Path.parent
Path.parent : func(path: Path -> Path?)
Returns the parent directory of the file or directory at the specified path.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file or directory. | - |
Return: The path of the parent directory or none if the path is (/) (the file root).
Example:
assert (./path/to/file.txt).parent() == (./path/to/)
Path.read
Path.read : func(path: Path -> Text?)
Reads the contents of the file at the specified path or none if the file could not be read.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to read. | - |
Return: The contents of the file. If the file could not be read, none will be returned. If the file can be read, but is not valid UTF8 data, an error will be raised.
Example:
assert (./hello.txt).read() == "Hello"
assert (./nosuchfile.xxx).read() == none
Path.read_bytes
Path.read_bytes : func(path: Path, limit: Int? = none -> [Byte]?)
Reads the contents of the file at the specified path or none if the file could not be read.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to read. | - |
| limit | Int? |
A limit to how many bytes should be read. | none |
Return: The byte contents of the file. If the file cannot be read, none will be returned.
Example:
assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]
assert (./nosuchfile.xxx).read_bytes() == none
Path.relative_to
Path.relative_to : func(path: Path, relative_to = (./) -> Path)
Returns the path relative to a given base path. By default, the base path is the current directory.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to convert. | - |
| relative_to | `` | The base path for the relative path. | (./) |
Return: A relative path from the reference point to the given path.
Example:
assert (./path/to/file.txt).relative_to((./path)) == (./to/file.txt)
assert (/tmp/foo).relative_to((/tmp)) == (./foo)
Path.remove
Path.remove : func(path: Path, ignore_missing = no -> Result)
Removes the file or directory at the specified path. A runtime error is raised if something goes wrong.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to remove. | - |
| ignore_missing | `` | Whether to ignore errors if the file or directory does not exist. | no |
Return: Either Success or Failure(reason).
Example:
(./file.txt).remove()!
Path.resolved
Path.resolved : func(path: Path, relative_to = (./) -> Path)
Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to resolve. | - |
| relative_to | `` | The base path for resolution. | (./) |
Return: The resolved absolute path.
Example:
assert (~/foo).resolved() == (/home/user/foo)
assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)
Path.set_owner
Path.set_owner : func(path: Path, owner: Text? = none, group: Text? = none, follow_symlinks: Bool = yes -> Result)
Set the owning user and/or group for a path.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to change the permissions for. | - |
| owner | Text? |
If non-none, the new user to assign to be the owner of the file. | none |
| group | Text? |
If non-none, the new group to assign to be the owner of the file. | none |
| follow_symlinks | Bool |
Whether to follow symbolic links. | yes |
Return: Either Success or Failure(reason).
Example:
(./file.txt).set_owner(owner="root", group="wheel")!
Path.sibling
Path.sibling : func(path: Path, name: Text -> Path)
Return a path that is a sibling of another path (i.e. has the same parent, but a different name). This is equivalent to .parent().child(name)
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
A path. | - |
| name | Text |
The name of a sibling file or directory. | - |
Return: A new path representing the sibling.
Example:
assert (/foo/baz).sibling("doop") == (/foo/doop)
Path.subdirectories
Path.subdirectories : func(path: Path, include_hidden = no -> [Path])
Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the directory. | - |
| include_hidden | `` | Whether to include hidden subdirectories (those starting with a .) |
no |
Return: A list of subdirectory paths.
Example:
assert (./directory).subdirectories() == [(./directory/subdir1), (./directory/subdir2)]
assert (./directory).subdirectories(include_hidden=yes) == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]
Path.unique_directory
Path.unique_directory : func(path: Path -> Path)
Generates a unique directory path based on the given path. Useful for creating temporary directories.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The base path for generating the unique directory. The last six letters of this path must be XXXXXX. |
- |
Return: A unique directory path after creating the directory.
Example:
created := (/tmp/my-dir.XXXXXX).unique_directory()
assert created.is_directory() == yes
created.remove()!
Path.walk
Path.walk : func(path: Path, include_hidden = no, follow_symlinks: Bool = no -> func(->Path?))
Returns an iterator that efficiently recursively walks over every file and subdirectory in a given directory. The iteration order is not defined, but in practice it may look a lot like a breadth-first traversal.
The path itself is always included in the iteration.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path to begin the walk. | - |
| include_hidden | `` | Whether to include hidden files (those starting with a .) |
no |
| follow_symlinks | Bool |
Whether to follow symbolic links. Caution: if set to 'yes', it is possible for this iterator to get stuck in a loop, using increasingly large amounts of memory. | no |
Return: An iterator that recursively walks over every file and subdirectory.
Example:
for p in (/tmp).walk()
say("File or dir: $p")
# The path itself is always included:
assert [p for p in (./file.txt).walk()] == [(./file.txt)]
Path.write
Path.write : func(path: Path, text: Text, permissions = Int32(0o644) -> Result)
Writes the given text to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to write to. | - |
| text | Text |
The text to write to the file. | - |
| permissions | `` | The permissions to set on the file if it is created. | Int32(0o644) |
Return: Either Success or Failure(reason).
Example:
(./file.txt).write("Hello, world!")!
Path.write_bytes
Path.write_bytes : func(path: Path, bytes: [Byte], permissions = Int32(0o644) -> Result)
Writes the given bytes to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to write to. | - |
| bytes | [Byte] |
A list of bytes to write to the file. | - |
| permissions | `` | The permissions to set on the file if it is created. | Int32(0o644) |
Return: Either Success or Failure(reason).
Example:
(./file.txt).write_bytes([104, 105])!
Path.write_unique
Path.write_unique : func(path: Path, text: Text -> Path)
Writes the given text to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The base path for generating the unique file. This path must include the string XXXXXX in the file base name. |
- |
| text | Text |
The text to write to the file. | - |
Return: The path of the newly created unique file.
Example:
created := (./file-XXXXXX.txt).write_unique("Hello, world!")!
assert created == (./file-27QHtq.txt)
assert created.read()! == "Hello, world!"
created.remove()!
Path.write_unique_bytes
Path.write_unique_bytes : func(path: Path, bytes: [Byte] -> Path)
Writes the given bytes to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The base path for generating the unique file. This path must include the string XXXXXX in the file base name. |
- |
| bytes | [Byte] |
The bytes to write to the file. | - |
Return: The path of the newly created unique file.
Example:
created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!
assert created == (./file-27QHtq.txt)
assert created.read_bytes()! == [1, 2, 3]
created.remove()!
Path.writer
Path.writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(text:Text, close:Bool=no -> Result))
Returns a function that can be used to repeatedly write to the same file.
The file writer will keep its file descriptor open after each write (unless the close argument is set to yes). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.
| Argument | Type | Description | Default |
|---|---|---|---|
| path | Path |
The path of the file to write to. | - |
| append | Bool |
If set to yes, writes to the file will append. If set to no, then the first write to the file will overwrite its contents and subsequent calls will append. |
no |
| permissions | Int32 |
The permissions to set on the file if it is created. | Int32(0o644) |
Return: Returns a function that can repeatedly write to the same file. If close is set to yes, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.
Example:
write := (./file.txt).writer()
write("Hello\n")!
write("world\n", close=yes)!
1 % API3 # Builtins5 # Path6 ## Path.accessed9 Path.accessed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)10 ```12 Gets the file access time of a file.14 Argument | Type | Description | Default15 ---------|------|-------------|---------19 **Return:** A 64-bit unix epoch timestamp representing when the file or directory was last accessed, or `none` if no such file or directory exists.22 **Example:**24 assert (./file.txt).accessed() == Int64(1704221100)25 assert (./not-a-file).accessed() == none27 ```28 ## Path.append31 Path.append : func(path: Path, text: Text, permissions: Int32 = Int32(0o644) -> Result)32 ```34 Appends the given text to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.36 Argument | Type | Description | Default37 ---------|------|-------------|---------40 permissions | `Int32` | The permissions to set on the file if it is being created. | `Int32(0o644)`45 **Example:**47 (./log.txt).append("extra line\n")!49 ```50 ## Path.append_bytes53 Path.append_bytes : func(path: Path, bytes: [Byte], permissions: Int32 = Int32(0o644) -> Result)54 ```56 Appends the given bytes to the file at the specified path, creating the file if it doesn't already exist. Failure to write will result in a runtime error.58 Argument | Type | Description | Default59 ---------|------|-------------|---------62 permissions | `Int32` | The permissions to set on the file if it is being created. | `Int32(0o644)`67 **Example:**69 (./log.txt).append_bytes([104, 105])!71 ```72 ## Path.base_name75 Path.base_name : func(path: Path -> Text)76 ```78 Returns the base name of the file or directory at the specified path.80 Argument | Type | Description | Default81 ---------|------|-------------|---------87 **Example:**89 assert (./path/to/file.txt).base_name() == "file.txt"91 ```92 ## Path.by_line95 Path.by_line : func(path: Path -> func(->Text?)?)96 ```98 Returns an iterator that can be used to iterate over a file one line at a time, or returns none if the file could not be opened.100 Argument | Type | Description | Default101 ---------|------|-------------|---------104 **Return:** An iterator that can be used to get lines from a file one at a time or none if the file couldn't be read.107 **Example:**109 # Safely handle file not being readable:110 if lines := (./file.txt).by_line()111 for line in lines112 say(line.upper())113 else114 say("Couldn't read file!")116 # Assume the file is readable and error if that's not the case:117 for line in (/dev/stdin).by_line()!118 say(line.upper())120 ```121 ## Path.byte_writer124 Path.byte_writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(bytes:[Byte], close:Bool=no -> Result))125 ```127 Returns a function that can be used to repeatedly write bytes to the same file.129 The file writer will keep its file descriptor open after each write (unless the `close` argument is set to `yes`). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.131 Argument | Type | Description | Default132 ---------|------|-------------|---------134 append | `Bool` | If set to `yes`, writes to the file will append. If set to `no`, then the first write to the file will overwrite its contents and subsequent calls will append. | `no`137 **Return:** Returns a function that can repeatedly write bytes to the same file. If `close` is set to `yes`, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.140 **Example:**142 write := (./file.txt).byte_writer()143 write("Hello\n".utf8())!144 write("world\n".utf8(), close=yes)!146 ```147 ## Path.can_execute150 Path.can_execute : func(path: Path -> Bool)151 ```153 Returns whether or not a file can be executed by the current user/group.155 Argument | Type | Description | Default156 ---------|------|-------------|---------159 **Return:** `yes` if the file or directory exists and the current user has execute permissions, otherwise `no`.162 **Example:**164 assert (/bin/sh).can_execute() == yes165 assert (/usr/include/stdlib.h).can_execute() == no166 assert (/non/existant/file).can_execute() == no168 ```169 ## Path.can_read172 Path.can_read : func(path: Path -> Bool)173 ```175 Returns whether or not a file can be read by the current user/group.177 Argument | Type | Description | Default178 ---------|------|-------------|---------181 **Return:** `yes` if the file or directory exists and the current user has read permissions, otherwise `no`.184 **Example:**186 assert (/usr/include/stdlib.h).can_read() == yes187 assert (/etc/shadow).can_read() == no188 assert (/non/existant/file).can_read() == no190 ```191 ## Path.can_write194 Path.can_write : func(path: Path -> Bool)195 ```197 Returns whether or not a file can be written by the current user/group.199 Argument | Type | Description | Default200 ---------|------|-------------|---------203 **Return:** `yes` if the file or directory exists and the current user has write permissions, otherwise `no`.206 **Example:**208 assert (/tmp).can_write() == yes209 assert (/etc/passwd).can_write() == no210 assert (/non/existant/file).can_write() == no212 ```213 ## Path.changed216 Path.changed : func(path: Path, follow_symlinks: Bool = yes -> Int64?)217 ```219 Gets the file change time of a file.221 This is the ["ctime"](https://en.wikipedia.org/wiki/Stat_(system_call)#ctime) of a file, which is _not_ the file creation time.223 Argument | Type | Description | Default224 ---------|------|-------------|---------228 **Return:** A 64-bit unix epoch timestamp representing when the file or directory was last changed, or `none` if no such file or directory exists.231 **Example:**233 assert (./file.txt).changed() == Int64(1704221100)234 assert (./not-a-file).changed() == none236 ```237 ## Path.child240 Path.child : func(path: Path, child: Text -> Path)241 ```243 Return a path that is a child of another path.245 Argument | Type | Description | Default246 ---------|------|-------------|---------253 **Example:**255 assert (./directory).child("file.txt") == (./directory/file.txt)257 ```258 ## Path.children261 Path.children : func(path: Path, include_hidden = no -> [Path])262 ```264 Returns a list of children (files and directories) within the directory at the specified path. Optionally includes hidden files. Child ordering is not specified.266 Argument | Type | Description | Default267 ---------|------|-------------|---------274 **Example:**276 assert (./directory).children(include_hidden=yes) == [(./directory/.git), (./directory/foo.txt)]278 ```279 ## Path.create_directory282 Path.create_directory : func(path: Path, permissions = Int32(0o755), recursive = yes -> Result)283 ```285 Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.288 Argument | Type | Description | Default289 ---------|------|-------------|---------292 recursive | `` | If set to `yes`, then recursively create any parent directories if they don't exist, otherwise fail if the parent directory does not exist. When set to `yes`, this function behaves like `mkdir -p`. | `yes`297 **Example:**299 (./new_directory).create_directory()!301 ```302 ## Path.current_dir305 Path.current_dir : func(-> Path)306 ```308 Creates a new directory at the specified path with the given permissions. If any of the parent directories do not exist, they will be created as needed.314 **Example:**316 assert Path.current_dir() == (/home/user/tomo)318 ```319 ## Path.each_child322 Path.each_child : func(path: Path, include_hidden = no -> func(->Path?)?)323 ```325 Returns an iterator over the children (files and directories) within the directory at the specified path. Optionally includes hidden files. Iteration order is not specified.327 Argument | Type | Description | Default328 ---------|------|-------------|---------332 **Return:** An iterator over the children in a directory or `none` if the path is not a directory or a symlink to a directory.335 **Example:**337 for child in (/dir).each_child()338 say("Child: $child")340 ```341 ## Path.exists344 Path.exists : func(path: Path -> Bool)345 ```347 Checks if a file or directory exists at the specified path.349 Argument | Type | Description | Default350 ---------|------|-------------|---------356 **Example:**358 assert (/).exists() == yes360 ```361 ## Path.expand_home364 Path.expand_home : func(path: Path -> Path)365 ```367 For home-based paths (those starting with `~`), expand the path to replace the tilde with and absolute path to the user's `$HOME` directory.369 Argument | Type | Description | Default370 ---------|------|-------------|---------373 **Return:** If the path does not start with a `~`, then return it unmodified. Otherwise, replace the `~` with an absolute path to the user's home directory.376 **Example:**378 # Assume current user is 'user'379 assert (~/foo).expand_home() == (/home/user/foo)380 # No change381 assert (/foo).expand_home() == (/foo)383 ```384 ## Path.extension387 Path.extension : func(path: Path, full: Bool = yes -> Text)388 ```390 Returns the file extension of the file at the specified path. Optionally returns the full extension.392 Argument | Type | Description | Default393 ---------|------|-------------|---------395 full | `Bool` | Whether to return everything after the first `.` in the base name, or only the last part of the extension. | `yes`397 **Return:** The file extension (not including the leading `.`) or an empty text if there is no file extension.400 **Example:**402 assert (./file.tar.gz).extension() == "tar.gz"403 assert (./file.tar.gz).extension(full=no) == "gz"404 assert (/foo).extension() == ""405 assert (./.git).extension() == ""407 ```408 ## Path.files411 Path.files : func(path: Path, include_hidden: Bool = no -> [Path])412 ```414 Returns a list of files within the directory at the specified path. Optionally includes hidden files.416 Argument | Type | Description | Default417 ---------|------|-------------|---------424 **Example:**426 assert (./directory).files(include_hidden=yes) == [(./directory/file1.txt), (./directory/file2.txt)]428 ```429 ## Path.glob432 Path.glob : func(path: Path -> [Path])433 ```435 Perform a globbing operation and return a list of matching paths. Some glob specific details:439 choices of patterns.443 Argument | Type | Description | Default444 ---------|------|-------------|---------445 path | `Path` | The path of the directory which may contain special globbing characters like `*`, `?`, or `{...}` | -450 **Example:**452 # Current directory includes: foo.txt, baz.txt, qux.jpg, .hidden453 assert (./*).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]454 assert (./*.txt).glob() == [(./foo.txt), (./baz.txt)]455 assert (./*.{txt,jpg}).glob() == [(./foo.txt), (./baz.txt), (./qux.jpg)]456 assert (./.*).glob() == [(./.hidden)]458 # Globs with no matches return an empty list:459 assert (./*.xxx).glob() == []461 ```462 ## Path.group465 Path.group : func(path: Path, follow_symlinks: Bool = yes -> Text?)466 ```468 Get the owning group of a file or directory.470 Argument | Type | Description | Default471 ---------|------|-------------|---------475 **Return:** The name of the group which owns the file or directory, or `none` if the path does not exist.478 **Example:**480 assert (/bin).group() == "root"481 assert (/non/existent/file).group() == none483 ```484 ## Path.has_extension487 Path.has_extension : func(path: Path, extension: Text -> Bool)488 ```490 Return whether or not a path has a given file extension.492 Argument | Type | Description | Default493 ---------|------|-------------|---------495 extension | `Text` | A file extension (leading `.` is optional). If empty, the check will test if the file does not have any file extension. | -500 **Example:**502 assert (/foo.txt).has_extension("txt") == yes503 assert (/foo.txt).has_extension(".txt") == yes504 assert (/foo.tar.gz).has_extension("gz") == yes505 assert (/foo.tar.gz).has_extension("zip") == no507 ```508 ## Path.is_directory511 Path.is_directory : func(path: Path, follow_symlinks = yes -> Bool)512 ```514 Checks if the path represents a directory. Optionally follows symbolic links.516 Argument | Type | Description | Default517 ---------|------|-------------|---------524 **Example:**526 assert (./directory/).is_directory() == yes527 assert (./file.txt).is_directory() == no529 ```530 ## Path.is_file533 Path.is_file : func(path: Path, follow_symlinks = yes -> Bool)534 ```536 Checks if the path represents a file. Optionally follows symbolic links.538 Argument | Type | Description | Default539 ---------|------|-------------|---------546 **Example:**548 assert (./file.txt).is_file() == yes549 assert (./directory/).is_file() == no551 ```552 ## Path.is_socket555 Path.is_socket : func(path: Path, follow_symlinks = yes -> Bool)556 ```558 Checks if the path represents a socket. Optionally follows symbolic links.560 Argument | Type | Description | Default561 ---------|------|-------------|---------568 **Example:**570 assert (./socket).is_socket() == yes572 ```573 ## Path.is_symlink576 Path.is_symlink : func(path: Path -> Bool)577 ```579 Checks if the path represents a symbolic link.581 Argument | Type | Description | Default582 ---------|------|-------------|---------588 **Example:**590 assert (./link).is_symlink() == yes592 ```593 ## Path.lines596 Path.lines : func(path: Path -> [Text]?)597 ```599 Returns a list with the lines of text in a file or returns none if the file could not be opened.601 Argument | Type | Description | Default602 ---------|------|-------------|---------608 **Example:**610 lines := (./file.txt).lines()!612 ```613 ## Path.matches_glob616 Path.matches_glob : func(path: Path, glob: Text -> Bool)617 ```619 Return whether or not a path matches a given glob.621 Argument | Type | Description | Default622 ---------|------|-------------|---------629 **Example:**631 assert (./file.txt).matches_glob("*.txt")632 assert (./file.c).matches_glob("*.{c,h}")634 ```635 ## Path.modified638 Path.modified : func(path: Path, follow_symlinks: Bool = yes -> Int64?)639 ```641 Gets the file modification time of a file.643 Argument | Type | Description | Default644 ---------|------|-------------|---------648 **Return:** A 64-bit unix epoch timestamp representing when the file or directory was last modified, or `none` if no such file or directory exists.651 **Example:**653 assert (./file.txt).modified() == Int64(1704221100)654 assert (./not-a-file).modified() == none656 ```657 ## Path.move660 Path.move : func(path: Path, dest: Path, allow_overwriting = no -> Result)661 ```663 Moves the file or directory from one location to another.665 Argument | Type | Description | Default666 ---------|------|-------------|---------669 allow_overwriting | `` | Whether to permit overwriting the destination if it is an existing file or directory. | `no`674 **Example:**676 (./file.txt).move(/tmp/renamed.txt)!678 ```679 ## Path.owner682 Path.owner : func(path: Path, follow_symlinks: Bool = yes -> Text?)683 ```685 Get the owning user of a file or directory.687 Argument | Type | Description | Default688 ---------|------|-------------|---------692 **Return:** The name of the user who owns the file or directory, or `none` if the path does not exist.695 **Example:**697 assert (/bin).owner() == "root"698 assert (/non/existent/file).owner() == none700 ```701 ## Path.parent704 Path.parent : func(path: Path -> Path?)705 ```707 Returns the parent directory of the file or directory at the specified path.709 Argument | Type | Description | Default710 ---------|------|-------------|---------716 **Example:**718 assert (./path/to/file.txt).parent() == (./path/to/)720 ```721 ## Path.read724 Path.read : func(path: Path -> Text?)725 ```727 Reads the contents of the file at the specified path or none if the file could not be read.729 Argument | Type | Description | Default730 ---------|------|-------------|---------733 **Return:** The contents of the file. If the file could not be read, none will be returned. If the file can be read, but is not valid UTF8 data, an error will be raised.736 **Example:**738 assert (./hello.txt).read() == "Hello"739 assert (./nosuchfile.xxx).read() == none741 ```742 ## Path.read_bytes745 Path.read_bytes : func(path: Path, limit: Int? = none -> [Byte]?)746 ```748 Reads the contents of the file at the specified path or none if the file could not be read.750 Argument | Type | Description | Default751 ---------|------|-------------|---------758 **Example:**760 assert (./hello.txt).read_bytes()! == [72, 101, 108, 108, 111]761 assert (./nosuchfile.xxx).read_bytes() == none763 ```764 ## Path.relative_to767 Path.relative_to : func(path: Path, relative_to = (./) -> Path)768 ```770 Returns the path relative to a given base path. By default, the base path is the current directory.772 Argument | Type | Description | Default773 ---------|------|-------------|---------780 **Example:**782 assert (./path/to/file.txt).relative_to((./path)) == (./to/file.txt)783 assert (/tmp/foo).relative_to((/tmp)) == (./foo)785 ```786 ## Path.remove789 Path.remove : func(path: Path, ignore_missing = no -> Result)790 ```792 Removes the file or directory at the specified path. A runtime error is raised if something goes wrong.794 Argument | Type | Description | Default795 ---------|------|-------------|---------802 **Example:**804 (./file.txt).remove()!806 ```807 ## Path.resolved810 Path.resolved : func(path: Path, relative_to = (./) -> Path)811 ```813 Resolves the absolute path of the given path relative to a base path. By default, the base path is the current directory.815 Argument | Type | Description | Default816 ---------|------|-------------|---------823 **Example:**825 assert (~/foo).resolved() == (/home/user/foo)826 assert (./path/to/file.txt).resolved(relative_to=(/foo)) == (/foo/path/to/file.txt)828 ```829 ## Path.set_owner832 Path.set_owner : func(path: Path, owner: Text? = none, group: Text? = none, follow_symlinks: Bool = yes -> Result)833 ```835 Set the owning user and/or group for a path.837 Argument | Type | Description | Default838 ---------|------|-------------|---------847 **Example:**849 (./file.txt).set_owner(owner="root", group="wheel")!851 ```852 ## Path.sibling855 Path.sibling : func(path: Path, name: Text -> Path)856 ```858 Return a path that is a sibling of another path (i.e. has the same parent, but a different name). This is equivalent to `.parent().child(name)`860 Argument | Type | Description | Default861 ---------|------|-------------|---------868 **Example:**870 assert (/foo/baz).sibling("doop") == (/foo/doop)872 ```873 ## Path.subdirectories876 Path.subdirectories : func(path: Path, include_hidden = no -> [Path])877 ```879 Returns a list of subdirectories within the directory at the specified path. Optionally includes hidden subdirectories.881 Argument | Type | Description | Default882 ---------|------|-------------|---------884 include_hidden | `` | Whether to include hidden subdirectories (those starting with a `.`) | `no`889 **Example:**891 assert (./directory).subdirectories() == [(./directory/subdir1), (./directory/subdir2)]892 assert (./directory).subdirectories(include_hidden=yes) == [(./directory/.git), (./directory/subdir1), (./directory/subdir2)]894 ```895 ## Path.unique_directory898 Path.unique_directory : func(path: Path -> Path)899 ```901 Generates a unique directory path based on the given path. Useful for creating temporary directories.903 Argument | Type | Description | Default904 ---------|------|-------------|---------905 path | `Path` | The base path for generating the unique directory. The last six letters of this path must be `XXXXXX`. | -910 **Example:**912 created := (/tmp/my-dir.XXXXXX).unique_directory()913 assert created.is_directory() == yes914 created.remove()!916 ```917 ## Path.walk920 Path.walk : func(path: Path, include_hidden = no, follow_symlinks: Bool = no -> func(->Path?))921 ```923 Returns an iterator that efficiently recursively walks over every file and subdirectory in a given directory. The iteration order is not defined, but in practice it may look a lot like a breadth-first traversal.925 The path itself is always included in the iteration.927 Argument | Type | Description | Default928 ---------|------|-------------|---------931 follow_symlinks | `Bool` | Whether to follow symbolic links. Caution: if set to 'yes', it is possible for this iterator to get stuck in a loop, using increasingly large amounts of memory. | `no`936 **Example:**938 for p in (/tmp).walk()939 say("File or dir: $p")941 # The path itself is always included:942 assert [p for p in (./file.txt).walk()] == [(./file.txt)]944 ```945 ## Path.write948 Path.write : func(path: Path, text: Text, permissions = Int32(0o644) -> Result)949 ```951 Writes the given text to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.953 Argument | Type | Description | Default954 ---------|------|-------------|---------962 **Example:**964 (./file.txt).write("Hello, world!")!966 ```967 ## Path.write_bytes970 Path.write_bytes : func(path: Path, bytes: [Byte], permissions = Int32(0o644) -> Result)971 ```973 Writes the given bytes to the file at the specified path, creating the file if it doesn't already exist. Sets the file permissions as specified. If the file writing cannot be successfully completed, a runtime error is raised.975 Argument | Type | Description | Default976 ---------|------|-------------|---------984 **Example:**986 (./file.txt).write_bytes([104, 105])!988 ```989 ## Path.write_unique992 Path.write_unique : func(path: Path, text: Text -> Path)993 ```995 Writes the given text to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.997 Argument | Type | Description | Default998 ---------|------|-------------|---------999 path | `Path` | The base path for generating the unique file. This path must include the string `XXXXXX` in the file base name. | -1005 **Example:**1007 created := (./file-XXXXXX.txt).write_unique("Hello, world!")!1008 assert created == (./file-27QHtq.txt)1009 assert created.read()! == "Hello, world!"1010 created.remove()!1012 ```1013 ## Path.write_unique_bytes1016 Path.write_unique_bytes : func(path: Path, bytes: [Byte] -> Path)1017 ```1019 Writes the given bytes to a unique file path based on the specified path. The file is created if it doesn't exist. This is useful for creating temporary files.1021 Argument | Type | Description | Default1022 ---------|------|-------------|---------1023 path | `Path` | The base path for generating the unique file. This path must include the string `XXXXXX` in the file base name. | -1029 **Example:**1031 created := (./file-XXXXXX.txt).write_unique_bytes([1, 2, 3])!1032 assert created == (./file-27QHtq.txt)1033 assert created.read_bytes()! == [1, 2, 3]1034 created.remove()!1036 ```1037 ## Path.writer1040 Path.writer : func(path: Path, append: Bool = no, permissions: Int32 = Int32(0o644) -> func(text:Text, close:Bool=no -> Result))1041 ```1043 Returns a function that can be used to repeatedly write to the same file.1045 The file writer will keep its file descriptor open after each write (unless the `close` argument is set to `yes`). If the file writer is never closed, it will be automatically closed when the file writer is garbage collected.1047 Argument | Type | Description | Default1048 ---------|------|-------------|---------1050 append | `Bool` | If set to `yes`, writes to the file will append. If set to `no`, then the first write to the file will overwrite its contents and subsequent calls will append. | `no`1053 **Return:** Returns a function that can repeatedly write to the same file. If `close` is set to `yes`, then the file will be closed after writing. If this function is called again after closing, the file will be reopened for appending.1056 **Example:**1058 write := (./file.txt).writer()1059 write("Hello\n")!1060 write("world\n", close=yes)!1062 ```