Files¶
Starkite scripts use the fs module to manage files, directories, and path resolutions. The module centers on the Path type, allowing scripts to execute filesystem reads, writes, deletions, and traversals directly through path-anchored methods.
Path instantiation and composition¶
To perform filesystem operations, instantiate a Path object using the fs.path() factory or the global alias path():
Once instantiated, you can query its properties to inspect path components:
| Property | Type | Description | Example (for path("/home/alice/report.md")) |
|---|---|---|---|
.name |
string |
The filename including its extension. | "report.md" |
.stem |
string |
The filename excluding the extension. | "report" |
.suffix |
string |
The file extension including the leading dot. | ".md" |
.parent |
Path |
The parent directory as a new Path object. |
path("/home/alice") |
.parts |
list[string] |
A list of individual path segments. | ["/", "home", "alice", "report.md"] |
.string |
string |
The clean string representation of the path. | "/home/alice/report.md" |
To compose and join new path segments, use the path slash operator (/) or the .join() method:
# Build a nested path using the path slash operator
config = path("/home/alice") / "config" / "app.yaml"
# Alternatively, join segments using the join() method
config = path("/home/alice").join("config", "app.yaml")
# Resolves to the absolute path: /home/alice/config/app.yaml
print(config.string)
File I/O operations¶
To read, write, or append data to a file, execute the corresponding methods directly on a Path object:
p = path("config.yaml")
# Read the entire file as a string
content = p.read_text()
# Overwrite or create a file with text (default mode is 0644)
path("/tmp/output.txt").write_text("hello world")
# Append text to the end of a file
path("/tmp/output.txt").append_text("\nsecond line")
Binary operations are supported via .read_bytes(), .write_bytes(), and .append_bytes():
# Read binary data from a file (returns a bytes object)
binary_data = path("image.png").read_bytes()
# Write raw bytes to a file
path("copy.png").write_bytes(binary_data)
# Append binary data to a file using a bytes literal
path("data.bin").append_bytes(b"\x00\xff\x00\xff")
Metadata and checks¶
You can query file types, check existence, and inspect system metadata:
.exists(): ReturnsTrueif the path exists on disk..is_file()/.is_dir()/.is_symlink(): Type-checking predicates..stat(): Returns a dictionary containing file details (name,size,mode,is_dir,mod_time)..disk_usage(): Returns a dictionary containing storage space info (total,used,freein bytes) for the partition hosting the path.
def main():
target = path("/var/log/syslog")
if target.exists() and target.is_file():
info = target.stat()
print("File size in bytes: " + str(info["size"]))
Directory traversal and globbing¶
To locate, list, or recursively traverse files in a directory, use the following methods:
.listdir(): Returns a list of immediate childPathobjects in the directory..glob(pattern): Searches the directory and returns a list of childPathobjects matching a wildcard glob pattern..walk(): Recursively traverses the directory tree, returning a list oftuple(dir_path, subdirs, files)identical to Python'sos.walk.
Traversal examples¶
def main():
# List all immediate logs in a directory
for entry in path("./logs").glob("*.log"):
print("Log file: " + entry.name)
# Recursively traverse and list all nested files
for dir_path, subdirs, files in path("./src").walk():
for f in files:
# Re-assemble the path using the path slash operator
full_path = dir_path / f
print("Found source file: " + full_path.string)
Common file operations¶
The Path object provides standard methods to manage files and directories:
| Method | Purpose |
|---|---|
.touch([exist_ok=True]) |
Creates an empty file or updates its modification time. |
.mkdir([parents=False, mode=0755]) |
Creates a new directory. Set parents=True to create intermediate parent folders. |
.remove() |
Deletes the file or empty directory. |
.rename(target_path) |
Renames or moves the file to a new path. |
.copy_to(target_path) |
Copies the file to a new destination. |
.move_to(target_path) |
Moves the file to a new destination. |
.expanduser() |
Resolves leading ~ or ~user home directory prefixes. |
# Create nested directories
path("./data/archive").mkdir(parents=True)
# Copy a file to a backup destination
path("config.json").copy_to("config.json.bak")
Permissions¶
All filesystem interactions are gated by Starkite's security engine. Reading from the filesystem requires the fs.read capability, and modifying or deleting files requires fs.write or fs.delete.
To run a script that accesses the filesystem, execute it with a permission profile like --allow-fs:
For more details, see the Permission Guide.
Failure handling¶
By default, executing an I/O operation on a missing file or path with insufficient permissions raises a Starlark-level execution error and terminates the script.
To handle failures programmatically without halting the script, append try_ to any I/O method name. These variants return a Result object:
def main():
# Safely attempt to read an optional configuration file
result = path("optional-settings.json").try_read_text()
if result.ok:
settings = result.value
else:
print("Skipping optional settings: " + result.error)
See also¶
fsAPI reference — Detailed function signatures and properties.