fs
The fs module provides functions and types for filesystem operations.
Types
Functions
open path mode? func?
Opens a file and returns a File object.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str |
Path to the file to open |
mode |
str |
File access mode (default: "r") |
func |
func | Callable to run with the file; auto-closes when done |
File modes:
| Mode | Description |
|---|---|
"r" |
Read-only |
"w" |
Write-only (truncates existing file) |
"a" |
Append to existing file |
"r+" |
Read and write |
"w+" |
Read and write (truncates existing file) |
"a+" |
Read and append |
Add "b" suffix for binary mode (e.g., "rb", "wb", "r+b").
Returns: File
Example:
# Read a file (auto-closed when block finishes)
open config.txt r do |file|
let content = file.read()
echo "Content: $content"
# Write with automatic cleanup
open output.txt w do |file|
file.write "Hello, World!"
# Manual file management
let file = open data.txt w
file.write "some data"
file.close()
remove path... :all? :ignore?
Removes one or more paths from the filesystem.
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 |
|---|---|---|
path |
str|Path |
One or more paths to remove |
all |
bool |
If true, removes directories recursively |
ignore |
bool |
If true, ignores a missing path |
Example:
write "temp.txt" "temporary data"
remove "temp.txt"
remove "missing.txt" ignore: true
remove "build" all: true
remove "a.txt" "b.txt"
exists path
Checks whether a file or directory exists at the given path.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to check for existence |
Returns: bool - true if the path
exists, false otherwise
Example:
# Check before removing
if exists "temp.txt"
remove "temp.txt"
echo "Removed temp.txt"
else
echo "temp.txt does not exist"
# Conditional file operations
if exists "config.yaml"
echo "Found config file"
read path mode?
Reads the entire contents of a file in one call.
By default, returns text as a str. If mode is
"b", returns raw bytes as bin.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to the file to read |
mode |
str |
Optional mode string; only "b" is allowed |
Example:
write path content
Writes the entire contents of a file in one call, creating or truncating the file.
Binary values are written as raw bytes. All other values are converted to a string first.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to the file to write |
content |
any | Value to write |
Returns: int - Number of bytes written
Example:
is_absolute path
Checks whether a path is absolute.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to check |
Returns: bool - true if the path is absolute,
false if relative
Example:
# Check different paths
if is_absolute "/etc/passwd"
echo "Absolute path"
if !is_absolute "./config.txt"
echo "Relative path"
metadata path :follow = true
Gets file metadata for the given path.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to the file or directory |
follow |
bool |
If false, returns metadata for symlink instead of target. |
Returns: Record with the following fields:
Always present:
| Field | Type | Description |
|---|---|---|
len |
int |
File size in bytes |
type |
sym |
File type: :file:, :dir:, :symlink:, or :unknown: |
Optional timestamps (platform-dependent):
| Field | Type | Description |
|---|---|---|
modified |
DateTime |
Last modification time |
accessed |
DateTime |
Last access time |
created |
DateTime |
Creation/change time |
Unix-only (not available on Windows):
| Field | Type | Description |
|---|---|---|
mode |
int |
File permissions and type (stat mode) |
dev |
int |
Device ID |
ino |
int |
Inode number |
nlink |
int |
Number of hard links |
uid |
int |
User ID of owner |
gid |
int |
Group ID of owner |
rdev |
int |
Device ID (if special file) |
blksize |
int |
Preferred block size for I/O |
blocks |
int |
Number of 512-byte blocks allocated |
Example:
let meta = metadata "data.txt"
echo "Size: $(meta.len)"
echo "Type: $(meta.type)"
if (meta.mode != nil)
echo "Mode: $(meta.mode)"
# Get symlink metadata without following
let link_meta = metadata "link.txt" follow: false
echo "Link type: $(link_meta.type)"
copy from to :all?
Copies a filesystem entry from one location to another.
By default this copies a single file or symlink. With all: true, it also
copies directories recursively.
Parameters:
| Name | Type | Description |
|---|---|---|
from |
str|Path |
Source path |
to |
str|Path |
Destination path |
all |
bool |
If true, allows recursive directory copy |
Example:
rename from to
Renames (moves) a file or directory.
Parameters:
| Name | Type | Description |
|---|---|---|
from |
str|Path |
Source path |
to |
str|Path |
Destination path |
Example:
rename "old_name.txt" "new_name.txt"
# Move to different directory
rename "file.txt" "subdir/file.txt"
move from to :all?
Moves a filesystem entry from one location to another.
This first tries a plain rename. If that fails because the source and
destination are on different filesystems, it falls back to copy-and-delete.
By default this moves a single file or symlink. With all: true, it also
moves directories recursively.
Parameters:
| Name | Type | Description |
|---|---|---|
from |
str|Path |
Source path |
to |
str|Path |
Destination path |
all |
bool |
If true, allows recursive directory move |
Example:
symlink src dst
Creates a symbolic link at dst pointing to src.
Platform Notes:
- Unix: Creates a standard symbolic link
- Windows: Attempts to determine if the target is a file or directory by
reading its metadata. If the target cannot be accessed, the operation fails.
For explicit control, use
symlink_fileorsymlink_dir.
Parameters:
| Name | Type | Description |
|---|---|---|
src |
str|Path |
Target path the symlink points to |
dst |
str|Path |
Path where the symlink is created |
Errors: Raises a runtime error if the target cannot be accessed on Windows.
Example:
symlink_dir src dst
Creates a directory symbolic link at dst pointing to src.
Platform Notes:
- Unix: Equivalent to
symlink - Windows: Creates a directory symlink (requires appropriate permissions on some Windows versions)
Parameters:
| Name | Type | Description |
|---|---|---|
src |
str|Path |
Target directory path |
dst |
str|Path |
Path where the symlink is created |
Example:
symlink_file src dst
Creates a file symbolic link at dst pointing to src.
Platform Notes:
- Unix: Equivalent to
symlink - Windows: Creates a file symlink (may require appropriate permissions on some Windows versions)
Parameters:
| Name | Type | Description |
|---|---|---|
src |
str|Path |
Target file path |
dst |
str|Path |
Path where the symlink is created |
Example:
entries path
Reads the entries in a directory.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to the directory |
Returns: Iterable of DirEntry objects
Example:
# Iterate over directory entries
for entry = entries /home/user/docs
echo "$(entry.name) - $(entry.type)"
# Collect into an array
let files = [...entries "."]
echo "Found $(files.len) entries"
create_dir path :all?
Creates a directory at the given path.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to the directory to create |
all |
bool |
If true, creates parent directories too |
Example:
# Create a single directory
create_dir new_dir
# Create directory and all parents
create_dir a/b/c all: true
remove_dir path... :all? :ignore?
Removes one or more directories.
By default this removes only empty directories. 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 |
|---|---|---|
path |
str|Path |
One or more directories to remove |
all |
bool |
If true, recursively prunes only empty directory subtrees |
ignore |
bool |
If true, ignores missing directories and file-blocked subtrees |
Example:
# Remove an empty directory
remove_dir empty_dir
# Remove an empty directory tree
remove_dir dir_to_remove all: true
# Prune only the empty branches and ignore file-blocked subtrees
remove_dir cache tmp all: true ignore: true
glob pattern :max_depth? :follow?
Returns an iterator over paths matching a glob pattern.
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
Glob pattern syntax:
*- Match any sequence of characters except path separator?- Match a single character**- Match any sequence of characters including path separators (recursive)[abc]- Match any character in the set{a,b,c}- Match any of the comma-separated patterns
Example:
# Find all text files
for path = glob "*.txt"
echo "Found: $path"
# Recursive search with depth limit
for path = glob "**/*.rs" max_depth: 3
echo "Source: $path"
# Follow symlinks
for path = glob "**/*" follow: true
echo "Entry: $path"
normal path
Returns a normalized path with . and .. components resolved without
accessing the filesystem.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to normalize |
Returns: Path - Normalized path
Example:
# Remove redundant components
let clean = normal "./foo/../bar/./baz"
echo $clean # bar/baz
# Works with Path objects too
let path = Path "a/b/../c"
let norm = normal $path
echo $norm # a/c
absolute path
Returns the absolute form of a path based on the current working directory.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to make absolute |
Returns: Path - Absolute path
Example:
let abs = absolute "./config.txt"
echo $abs # /current/working/dir/config.txt
# Already absolute paths are unchanged
let unchanged = absolute "/etc/passwd"
echo $unchanged # /etc/passwd
relative path base?
Returns the path relative to a base directory.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to make relative |
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 rel = relative "/home/user/docs/file.txt"
echo $rel # docs/file.txt (if cwd is /home/user)
# Relative to specific base
let rel2 = relative "/a/b/c/d" "/a/b"
echo $rel2 # c/d
# Returns original if no common prefix
let unchanged = relative "/etc/passwd" "/home/user"
echo $unchanged # /etc/passwd
chmod path mode
Changes the permissions of a file or directory.
Platform Notes:
- Unix: Changes file permissions using standard Unix mode bits
- Windows: Raises a runtime error (not supported)
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to the file or directory |
mode |
int |
Permission mode bits (e.g., 0o755) |
Errors: Raises a runtime error on non-Unix platforms or if the operation fails.
Example:
# Set file permissions to rwxr-xr-x (755)
chmod "script.sh" 0o755
# Set directory permissions to rwxrwxrwx (777)
chmod "/tmp/shared" 0o777
# Remove write permissions for group and others
chmod "readonly.txt" 0o444
set_timestamps path :modified? :accessed? :created?
Updates the timestamps of a file or directory.
Platform Notes:
- Unix:
modifiedandaccessedare available;createdis not supported - Windows:
modified,accessed, andcreatedare available
Unspecified timestamps are left unchanged.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to update |
modified |
DateTime |
Optional new modification time |
accessed |
DateTime |
Optional new access time |
created |
DateTime |
Optional new creation time (Windows only) |
Errors: Raises a runtime error if created is used on unsupported
platforms or if the operation fails.
import time:
- DateTime
set_timestamps "artifact.tar" modified: DateTime.from_unix(1700000000)
set_timestamps "cache.db" accessed: DateTime.now()
set_timestamps "cache.db" created: DateTime.from_unix(1690000000)
chown path user? :group? :follow = true
Changes the owner and/or group of a file, directory, or symlink target.
Platform Notes:
- Unix: Available
- Windows: Not available
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to update |
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:
chown "script.sh" "deploy"
chown "artifact" group: "build"
chown "cache" 1000 group: 1000
chown "link" group: "www-data" follow: false
canonical path
Returns the canonical, absolute form of a path with all intermediate components normalized and symbolic links resolved.
Parameters:
| Name | Type | Description |
|---|---|---|
path |
str|Path |
Path to canonicalize |
Returns: Path - Canonical path
Example:
with_temp_dir func
Creates a temporary directory, invokes a callable with the directory path, then removes the directory recursively upon return or error.
Parameters:
| Name | Type | Description |
|---|---|---|
func |
func | Called with a Path to the temp dir |
parent |
path | Parent directory for the temporary directory |
Platform Notes:
The default parent of the temporary directory is chosen as follows:
- Windows: Uses the directory returned by
GetTempPath2 - Unix: Uses
TMPDIRfrom the strand-local environment if set, otherwise/tmp
Example: