shell
stableExecute shell commands, manage environment variables, and perform file system operations including path manipulation, directory traversal, and file I/O.
use plugin shell::{exec, exec_status, exec_lines, …} Functions (46)
- exec Run a shell command, return stdout/stderr/exit_code
- exec_status Run a command, return only the exit code
- exec_lines Run a command, return stdout as a table of lines
- exec_env Run a command with extra environment variables
- exec_in_dir Run a command in a specific working directory
- pipe Chain multiple commands with pipes
- which Find the path to a program on PATH
- env_get Read an environment variable
- env_set Set an environment variable
- env_remove Remove an environment variable
- env_list List all environment variables
- cwd Get the current working directory
- chdir Change the current working directory
- home_dir Get the user's home directory
- temp_dir Get the system temporary directory
- path_separator Get the OS path separator character
- os Get the operating system name
- arch Get the CPU architecture name
- is_windows Check if running on Windows
- is_linux Check if running on Linux
- is_macos Check if running on macOS
- glob Match file paths using a glob pattern
- exists Check if a path exists
- is_file Check if a path is a regular file
- is_dir Check if a path is a directory
- file_size Get a file's size in bytes
- read_file Read a file's content as a string
- write_file Write a string to a file
- append_file Append a string to a file
- mkdir Create a directory (and parents)
- rmdir Remove a directory recursively
- copy_file Copy a file to another path
- move_file Move or rename a file
- remove_file Delete a file
- list_dir List entries in a directory
- walk_dir Recursively list all files in a directory
- path_join Join path parts into a single path
- path_parent Get the parent directory of a path
- path_filename Get the filename component of a path
- path_extension Get the file extension of a path
- path_stem Get the filename without its extension
- absolute_path Resolve a path to its canonical absolute form
- shell_execute Open a file or URL with the OS shell verb
- resolve_shortcut Resolve a Windows .lnk shortcut file
- extract_icon Extract an icon from a file as PNG bytes
- read_directory_items List directory entries with metadata
Overview
shell is the systems-programming bridge between a Zolo script and the host
operating system. It groups three concerns under one plugin: running external
commands (exec, pipe, exec_in_dir, …), reading and writing the
environment (env_get, cwd, os, which, …), and manipulating the file
system and paths (read_file, mkdir, glob, path_join, walk_dir, …).
There is no handle or stateful object to manage — every function is a free call
that acts directly on the live process, so changes such as chdir or env_set
affect the running script immediately.
Command functions return a table with stdout, stderr, and exit_code so you
can inspect output and success in one place; path and file helpers return plain
strings, booleans, or tables. A few functions are platform-specific
(resolve_shortcut, extract_icon are Windows-only; shell_execute maps to
ShellExecuteW on Windows and xdg-open elsewhere), so guard them with os() or
is_windows() when writing cross-platform code.
Common patterns
Run a command and branch on its exit code:
use plugin shell::{exec}
let result = exec("cargo build --release")
if result["exit_code"] == 0 {
print("build ok")
} else {
print("build failed:\n{result["stderr"]}")
}
Build a path, make sure its directory exists, then write to it:
use plugin shell::{path_join, mkdir, write_file, home_dir}
let dir = path_join([home_dir(), "reports"])
mkdir(dir)
let file = path_join([dir, "summary.txt"])
write_file(file, "generated by zolo\n")
print("wrote {file}")
Find every Zolo source file under a tree and report its size:
use plugin shell::{glob, file_size, path_filename}
let files = glob("src/**/*.zolo")
for _, path in files {
print("{path_filename(path)}: {file_size(path)} bytes")
}
Run a shell command, return stdout/stderr/exit_code
Runs a shell command and returns a table with stdout, stderr, and exit_code. Use this when you need the full output of a command.
use plugin shell::{exec}
let result = exec("git log --oneline -5")
print(result["stdout"])
print("exit: {result["exit_code"]}")
Inspect both streams to surface a failure message:
use plugin shell::{exec}
let r = exec("ls /does-not-exist")
if r["exit_code"] != 0 {
print("error: {r["stderr"]}")
}
Run a command, return only the exit code
Runs a command and returns only the exit code as an integer. Use this to check whether a command succeeded (0 = success).
use plugin shell::{exec_status}
let code = exec_status("cargo test")
if code == 0 {
print("tests passed")
} else {
print("tests failed with code {code}")
}
Run a command, return stdout as a table of lines
Runs a command and returns stdout as a table indexed by line number. Convenient for processing line-by-line output.
use plugin shell::{exec_lines}
let lines = exec_lines("ls -1")
for _, line in lines {
print(line)
}
Run a command with extra environment variables
Runs a command with additional environment variables supplied as a table. Returns stdout, stderr, and exit_code.
use plugin shell::{exec_env}
let result = exec_env("printenv MY_VAR", #{"MY_VAR": "hello"})
print(result["stdout"])
Run a command in a specific working directory
Runs a command with its working directory set to dir. Returns stdout, stderr, and exit_code.
use plugin shell::{exec_in_dir}
let result = exec_in_dir("cargo build --release", "/home/user/myproject")
print(result["stdout"])
Chain multiple commands with pipes
Chains an array of commands with Unix pipes and returns stdout, stderr, and exit_code.
use plugin shell::{pipe}
let result = pipe(["ps aux", "grep rust", "wc -l"])
print("rust processes: {result["stdout"]}")
Count the lines in a file by chaining cat into wc:
use plugin shell::{pipe}
let r = pipe(["cat access.log", "wc -l"])
print("log lines: {r["stdout"]}")
Find the path to a program on PATH
Returns the full path to program if found on PATH, or nil if not found.
use plugin shell::{which}
let path = which("cargo")
if path != nil {
print("cargo is at {path}")
}
Read an environment variable
Returns the value of the environment variable name, or nil if not set.
use plugin shell::{env_get}
let home = env_get("HOME")
print("home is {home}")
Fall back to a default when the variable is unset:
use plugin shell::{env_get}
let level = env_get("LOG_LEVEL")
if level == nil {
level = "info"
}
print("log level: {level}")
Set an environment variable
Sets the environment variable name to value for the current process.
use plugin shell::{env_set}
env_set("DEBUG", "1")
Remove an environment variable
Removes the environment variable name from the current process.
use plugin shell::{env_remove}
env_remove("DEBUG")
List all environment variables
Returns a table of all current environment variables as key-value pairs.
use plugin shell::{env_list}
let vars = env_list()
for key, val in vars {
print("{key}={val}")
}
Get the current working directory
Returns the current working directory as an absolute path string.
use plugin shell::{cwd}
print("working in: {cwd()}")
Change the current working directory
Changes the current working directory to path.
use plugin shell::{chdir, cwd}
chdir("/tmp")
print(cwd())
Get the user's home directory
Returns the user's home directory path, or nil if it cannot be determined.
use plugin shell::{home_dir}
print("home: {home_dir()}")
Get the system temporary directory
Returns the system temporary directory path.
use plugin shell::{temp_dir}
print("temp: {temp_dir()}")
Get the OS path separator character
Returns the OS-specific path separator (/ on Unix, \ on Windows).
use plugin shell::{path_separator}
print("separator: {path_separator()}")
Get the operating system name
Returns the operating system identifier string, e.g. "windows", "linux", or "macos".
use plugin shell::{os}
print("running on: {os()}")
Get the CPU architecture name
Returns the CPU architecture string, e.g. "x86_64" or "aarch64".
use plugin shell::{arch}
print("arch: {arch()}")
Check if running on Windows
Returns true if the current platform is Windows.
use plugin shell::{is_windows}
if is_windows() {
print("on Windows")
}
Check if running on Linux
Returns true if the current platform is Linux.
use plugin shell::{is_linux}
if is_linux() {
print("on Linux")
}
Check if running on macOS
Returns true if the current platform is macOS.
use plugin shell::{is_macos}
if is_macos() {
print("on macOS")
}
Match file paths using a glob pattern
Returns a table of file paths matching the glob pattern. Supports *, **, and ? wildcards.
use plugin shell::{glob}
let files = glob("src/**/*.zolo")
for _, path in files {
print(path)
}
Glob a flat directory for a single extension:
use plugin shell::{glob, path_stem}
let images = glob("assets/*.png")
for _, p in images {
print("image: {path_stem(p)}")
}
Check if a path exists
Returns true if path exists (as a file or directory).
use plugin shell::{exists}
if exists("/etc/hosts") {
print("hosts file found")
}
Check if a path is a regular file
Returns true if path exists and is a regular file.
use plugin shell::{is_file}
print(is_file("README.md"))
Check if a path is a directory
Returns true if path exists and is a directory.
use plugin shell::{is_dir}
print(is_dir("/tmp"))
Get a file's size in bytes
Returns the size of the file at path in bytes.
use plugin shell::{file_size}
let size = file_size("archive.zip")
print("size: {size} bytes")
Read a file's content as a string
Reads the entire content of the file at path and returns it as a string.
use plugin shell::{read_file}
let content = read_file("config.toml")
print(content)
Guard the read with exists so a missing file does not error:
use plugin shell::{exists, read_file}
if exists("notes.md") {
print(read_file("notes.md"))
} else {
print("no notes yet")
}
Write a string to a file
Writes content to the file at path, creating or overwriting it.
use plugin shell::{write_file}
write_file("output.txt", "Hello, world!")
Append a string to a file
Appends content to the end of the file at path, creating it if it does not exist.
use plugin shell::{append_file}
append_file("log.txt", "new log entry\n")
Create a directory (and parents)
Creates a directory at path, including all intermediate parent directories.
use plugin shell::{mkdir}
mkdir("build/output/assets")
Remove a directory recursively
Removes the directory at path and all its contents recursively.
use plugin shell::{rmdir}
rmdir("build/output")
Copy a file to another path
Copies the file from src to dst.
use plugin shell::{copy_file}
copy_file("config.toml", "config.toml.bak")
Move or rename a file
Moves or renames the file from src to dst.
use plugin shell::{move_file}
move_file("temp_output.txt", "final_output.txt")
Delete a file
Deletes the file at path.
use plugin shell::{remove_file}
remove_file("temp.txt")
List entries in a directory
Lists entries in the directory at path. Each entry is a table with name, is_dir, and size.
use plugin shell::{list_dir}
let entries = list_dir(".")
for _, entry in entries {
print("{entry["name"]} - dir: {entry["is_dir"]}")
}
List only the subdirectories of a path:
use plugin shell::{list_dir}
let entries = list_dir("/home/user")
for _, entry in entries {
if entry["is_dir"] {
print("dir: {entry["name"]}")
}
}
Recursively list all files in a directory
Recursively walks path and returns a flat table of all file paths found.
use plugin shell::{walk_dir}
let files = walk_dir("src")
for _, f in files {
print(f)
}
Join path parts into a single path
Joins a table of path parts into a single path using the OS separator.
use plugin shell::{path_join}
let p = path_join(["home", "user", "documents", "file.txt"])
print(p)
Combine with cwd to build an absolute path under the working directory:
use plugin shell::{path_join, cwd}
let target = path_join([cwd(), "dist", "bundle.js"])
print(target)
Get the parent directory of a path
Returns the parent directory of path, or nil if there is no parent.
use plugin shell::{path_parent}
print(path_parent("/home/user/file.txt"))
Get the filename component of a path
Returns the final filename component of path, including the extension.
use plugin shell::{path_filename}
print(path_filename("/home/user/file.txt"))
Get the file extension of a path
Returns the file extension of path (without the leading dot), or nil.
use plugin shell::{path_extension}
print(path_extension("archive.tar.gz"))
Get the filename without its extension
Returns the filename without its extension.
use plugin shell::{path_stem}
print(path_stem("report.pdf"))
Resolve a path to its canonical absolute form
Resolves path to its canonical absolute path, resolving symlinks and .. components.
use plugin shell::{absolute_path}
print(absolute_path("../src"))
Open a file or URL with the OS shell verb
Opens a file or URL using the OS shell (ShellExecuteW on Windows, xdg-open on Linux). Returns a result code. verb, args, and cwd are optional.
use plugin shell::{shell_execute}
shell_execute("https://zolo-lang.dev", nil, nil, nil)
Resolve a Windows .lnk shortcut file
Resolves a Windows .lnk shortcut and returns a table with target, args, working_dir, description, icon_location, and icon_index. Windows-only.
use plugin shell::{resolve_shortcut}
let info = resolve_shortcut("C:\\Users\\user\\Desktop\\MyApp.lnk")
print(info["target"])
Extract an icon from a file as PNG bytes
Extracts the icon associated with a file and returns it as PNG bytes (the registered return type is any). size selects the icon resolution (16, 32, 48, 256). Windows-only.
use plugin shell::{extract_icon, write_file}
let png = extract_icon("C:\\Windows\\notepad.exe", 32)
List directory entries with metadata
Lists directory entries with rich metadata: name, full_path, is_shortcut, is_directory, size, and modified_unix.
use plugin shell::{read_directory_items}
let items = read_directory_items("C:\\Users\\user\\Desktop")
for _, item in items {
print("{item["name"]} shortcut={item["is_shortcut"]}")
}