Path
Path objects represent filesystem paths and provide methods for path manipulation and file operations.
Fields
name
Returns the final component of the path, or nil if the path is empty.
stem
Returns the final component without its last extension, or nil if the path is
empty.
let path = Path "/home/user/archive.tar.gz"
echo $path.stem # archive.tar
let no_ext = Path "/home/user/Makefile"
echo $no_ext.stem # Makefile
parent
Returns the parent directory as a new Path, or nil if the path is empty or
contains only one component.
ext
Returns the file extension (without the leading dot), or nil if the final
component has no extension.
let path = Path "/home/user/file.txt"
echo $path.ext # txt
let no_ext = Path "/home/user/noextension"
echo $no_ext.ext # nil
is_absolute
Returns whether the path is absolute (starts from the filesystem root).
let abs = Path "/home/user/file.txt"
echo $abs.is_absolute # true
let rel = Path "./file.txt"
echo $rel.is_absolute # false
Class Methods
(init) path
Constructs a new path.
| Name | Type | Description |
|---|---|---|
path |
str|Path |
The path |
join ...components
Joins multiple path components into a single path. Components may be Path objects or strings.
If any component is an absolute path, it replaces everything before it.
Parameters:
| Name | Type | Description |
|---|---|---|
components |
str|Path |
Path components to join |
Returns: Path
Example:
let path = Path.join home user docs file.txt
echo $path.name # file.txt
# Absolute path replaces everything before it
let abs = Path.join home /etc config.txt
echo $abs # /etc/config.txt
Methods
open :mode? :block?
Opens the file at this path. Equivalent to open but with a Path
object.
Parameters:
| Name | Type | Description |
|---|---|---|
mode |
str |
File access mode (default: "r") |
block |
func | Callable to run with the file; auto-closes when done |
Returns: File
Example:
metadata :follow = false
Gets metadata for the file at this path.
Parameters:
| Name | Type | Description |
|---|---|---|
follow |
bool |
If false, returns metadata for a symlink rather than its target |
Returns: Record with the same fields as File.metadata
Example:
let path = Path config.json
let meta = path.metadata()
echo "Size: $(meta.len) bytes"
# Get symlink metadata without following
let link = Path "link.txt"
let link_meta = link.metadata follow: false
echo "Link points to: $(link_meta.type)"
exists()
Checks if the path exists.
Equivalent to the free function exists.
Returns: bool
Example:
read mode?
Reads the entire contents of the file at this path.
Equivalent to read.
Parameters:
| Name | Type | Description |
|---|---|---|
mode |
str |
Optional mode string; only "b" is allowed |
Example:
write content
Writes the entire contents of the file at this path, creating or truncating the file.
Equivalent to write.
Parameters:
| Name | Type | Description |
|---|---|---|
content |
any | Value to write |
Returns: int - Number of bytes written
Example:
copy to :all?
Copies this filesystem entry to to.
Equivalent to copy.
By default this copies a single file or symlink. With all: true, it also
copies directories recursively.
Parameters:
| Name | Type | Description |
|---|---|---|
to |
str|Path |
Destination path |
all |
bool |
If true, allows recursive directory copy |
Example:
let src = Path "source.txt"
src.copy "backup.txt"
let dir = Path "project"
dir.copy "project-backup" all: true
rename to
Renames this path to to.
Equivalent to rename.
Parameters:
| Name | Type | Description |
|---|---|---|
to |
str|Path |
Destination path |
Example:
move to :all?
Moves this filesystem entry to to.
Equivalent to move.
By default this moves a single file or symlink. With all: true, it also
moves directories recursively.
Parameters:
| Name | Type | Description |
|---|---|---|
to |
str|Path |
Destination path |
all |
bool |
If true, allows recursive directory move |
Example:
let src = Path "source.txt"
src.move "dest.txt"
let dir = Path "project"
dir.move "archive/project" all: true
entries()
Reads the entries in the directory at this path.
Returns: Iterable of DirEntry objects
Example:
let dir = Path /home/user/docs
# Iterate over directory entries
for entry = dir.entries()
echo "$(entry.name) - $(entry.type)"
# Collect into an array
let files = [...dir.entries()]
echo "Found $(files.len) entries"
add_ext ext
Returns a new path with ext appended as an additional extension.
Parameters:
| Name | Type | Description |
|---|---|---|
ext |
str |
Extension to append |
Returns: Path
Example:
let path = Path "archive.tar"
echo path.add_ext "gz" # archive.tar.gz
let file = Path "report"
echo file.add_ext "txt" # report.txt
canonical()
Returns the canonical, absolute form of the path with all intermediate components normalized and symbolic links resolved.
Returns: Path
Example:
read_link()
Reads the target of a symbolic link.
Returns: Path - The path that the symlink points to
Errors: Raises a runtime error if the path is not a symbolic link or cannot be read.
Example:
remove :all? :ignore?
Removes this path.
Equivalent to remove.
By default this removes a single file or symlink. With all: true, it also
removes directories recursively, similar to rm -r. With ignore: true,
missing paths are treated as success.
Parameters:
| Name | Type | Description |
|---|---|---|
all |
bool |
If true, removes directories recursively |
ignore |
bool |
If true, ignores a missing path |
Example:
let file = Path "temp.txt"
file.remove()
let dir = Path "build"
dir.remove all: true
dir.remove ignore: true
create_dir :all?
Creates a directory at this path.
Parameters:
| Name | Type | Description |
|---|---|---|
all |
bool |
If true, creates parent directories too |
Example:
let dir = Path "new_subdir"
dir.create_dir()
# Create with parents
let nested = Path "a/b/c"
nested.create_dir all: true
remove_dir :all? :ignore?
Removes the directory at this path.
By default this removes only an empty directory. With all: true, it removes
directories recursively, but only through subtrees that contain directories and
no files or other non-directory entries. Use
remove to delete directories that
contain files.
Parameters:
| Name | Type | Description |
|---|---|---|
all |
bool |
If true, recursively prunes only empty directory subtrees |
ignore |
bool |
If true, ignores missing directories and file-blocked subtrees |
Example:
let dir = Path "empty_dir"
dir.remove_dir()
# Remove an empty directory tree
let to_remove = Path "old_project"
to_remove.remove_dir all: true
to_remove.remove_dir all: true ignore: true
chmod mode
Changes the permissions of the file or directory at this path.
Platform Notes:
- Unix: Changes file permissions using standard Unix mode bits
- Windows: Raises a runtime error (not supported)
Parameters:
| Name | Type | Description |
|---|---|---|
mode |
int |
Permission mode bits (e.g., 0o755) |
Errors: Raises a runtime error on non-Unix platforms or if the operation fails.
Example:
set_timestamps :modified? :accessed? :created?
Updates the timestamps of the file or directory at this path.
Platform Notes:
- Unix:
modifiedandaccessedare available;createdis not supported - Windows:
modified,accessed, andcreatedare available
Unspecified timestamps are left unchanged.
Parameters:
| Name | Type | Description |
|---|---|---|
modified |
DateTime |
Optional new modification time |
accessed |
DateTime |
Optional new access time |
created |
DateTime |
Optional new creation time (Windows only) |
import time:
- DateTime
let artifact = Path "artifact.tar"
artifact.set_timestamps modified: DateTime.from_unix(1700000000)
artifact.set_timestamps accessed: DateTime.now()
artifact.set_timestamps created: DateTime.from_unix(1690000000)
chown user? :group? :follow = true
Changes the owner and/or group of the file, directory, or symlink target at this path.
Platform Notes:
- Unix: Available
- Windows: Not available
Parameters:
| Name | Type | Description |
|---|---|---|
user |
int|str |
Optional owner UID or user name |
group |
int|str |
Optional group GID or group name |
follow |
bool |
If false, operate on the symlink itself |
At least one of user or group must be provided.
Example:
let script = Path "script.sh"
script.chown "deploy" group: "deploy"
let shared = Path "/tmp/shared"
shared.chown group: "build"
let link = Path "current"
link.chown group: 33 follow: false
normal()
Returns a normalized path with . and .. components resolved without
accessing the filesystem.
Returns: Path
Example:
absolute()
Returns the absolute form of this path based on the current working directory.
If the path is already absolute, it is returned unchanged.
Returns: Path
Example:
let rel = Path "./config.txt"
let abs = rel.absolute()
echo $abs # /current/working/dir/config.txt
# Already absolute paths are unchanged
let already_abs = Path "/etc/passwd"
echo $already_abs.absolute() # /etc/passwd
relative(base?)
Returns this path relative to a base directory.
Parameters:
| Name | Type | Description |
|---|---|---|
base |
str|Path |
Base directory (default: cwd) |
Returns: Path - Relative path, or the original path if it cannot be made relative
Example:
# Relative to current directory
let path = Path "/home/user/docs/file.txt"
echo path.relative() # docs/file.txt (if cwd is /home/user)
# Relative to specific base
let path2 = Path "/a/b/c/d"
echo path2.relative "/a/b" # c/d
# Returns original if no common prefix
let path3 = Path "/etc/passwd"
echo path3.relative "/home/user" # /etc/passwd
glob pattern :max_depth? :follow?
Returns an iterator over paths matching a glob pattern relative to this path.
Parameters:
| Name | Type | Description |
|---|---|---|
pattern |
str |
Glob pattern (e.g., "*.txt", "**/*.rs") |
max_depth |
int |
Maximum directory depth to traverse (default: unlimited) |
follow |
bool |
Whether to follow symbolic links when traversing (default: false) |
Returns: Iterable of Path objects
Example: