Skip to content

shell

stable

Execute 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, …}
46 functions Systems
/ filter jk navigate Esc clear
Functions (46)
  1. exec Run a shell command, return stdout/stderr/exit_code
  2. exec_status Run a command, return only the exit code
  3. exec_lines Run a command, return stdout as a table of lines
  4. exec_env Run a command with extra environment variables
  5. exec_in_dir Run a command in a specific working directory
  6. pipe Chain multiple commands with pipes
  7. which Find the path to a program on PATH
  8. env_get Read an environment variable
  9. env_set Set an environment variable
  10. env_remove Remove an environment variable
  11. env_list List all environment variables
  12. cwd Get the current working directory
  13. chdir Change the current working directory
  14. home_dir Get the user's home directory
  15. temp_dir Get the system temporary directory
  16. path_separator Get the OS path separator character
  17. os Get the operating system name
  18. arch Get the CPU architecture name
  19. is_windows Check if running on Windows
  20. is_linux Check if running on Linux
  21. is_macos Check if running on macOS
  22. glob Match file paths using a glob pattern
  23. exists Check if a path exists
  24. is_file Check if a path is a regular file
  25. is_dir Check if a path is a directory
  26. file_size Get a file's size in bytes
  27. read_file Read a file's content as a string
  28. write_file Write a string to a file
  29. append_file Append a string to a file
  30. mkdir Create a directory (and parents)
  31. rmdir Remove a directory recursively
  32. copy_file Copy a file to another path
  33. move_file Move or rename a file
  34. remove_file Delete a file
  35. list_dir List entries in a directory
  36. walk_dir Recursively list all files in a directory
  37. path_join Join path parts into a single path
  38. path_parent Get the parent directory of a path
  39. path_filename Get the filename component of a path
  40. path_extension Get the file extension of a path
  41. path_stem Get the filename without its extension
  42. absolute_path Resolve a path to its canonical absolute form
  43. shell_execute Open a file or URL with the OS shell verb
  44. resolve_shortcut Resolve a Windows .lnk shortcut file
  45. extract_icon Extract an icon from a file as PNG bytes
  46. 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"]}")
}
enespt-br