comp
global:comp
Comparison operators
comp:gt
comp:gt left=any right=any
True if left side is greater than right side
Output
bool
In expression mode, this method can be used via the the > operator.
This command accepts the following arguments:
leftthe left side of the comparison.rightthe right side of the comparison.
Examples
gt 10 5
(10 > 5)
comp:gte
comp:gte left=any right=any
True if left side is greater than or equal right side
Output
bool
In expression mode, this method can be used via the the >= operator.
This command accepts the following arguments:
leftthe left side of the comparison.rightthe right side of the comparison.
Examples
gte 10 5
(10 >= 5)
comp:lt
comp:lte
comp:lte left=any right=any
True if left side is less than or equal than right side
Output
bool
In expression mode, this method can be used via the the <= operator.
This command accepts the following arguments:
leftthe left side of the comparison.rightthe right side of the comparison.
Examples
lte 10 5
(10 <= 5)
comp:neq
comp:neq left=any right=any
True if left side is not equal to right side
Output
bool
In expression mode, this method can be used via the the != operator.
This command accepts the following arguments:
leftthe left side of the comparison.rightthe right side of the comparison.
Examples
ne 10 5
(10 != 5)
comp:not
cond
cond:and
and condition:(bool|command)... -> boolean
True if all arguments are true
Every argument to and must be either a boolean or a command that returns a boolean. The and command will check all arguments in order, and if any of them are false, and will return false. If all conditions are true, and returns true.
Do note that and is a short circuiting command, meaning that if one of the conditions
is found to be false, and will not evaluate any remaining closures.
In expression mode, this method can be used via the the and operator.
Examples
# true, if $file exists and is a symlink
and $($file:exists) {$(stat $file)[0]:is_symlink}
# true, if $file exists and is a symlink
($file.exists() and {stat($file)[0].is_symlink})
cond:or
or condition:(bool|command)... -> boolean
True if any argument is true
Every argument to or must be either a boolean or a command that returns a boolean.
The or command will check all arguments in order, and if any of them are true, or
will return true. If all conditions are false, or returns false.
Do note that or is a short circuiting command, meaning that if one of the conditions
is found to be true, or will not evaluate any remaining closures.
In expression mode, this method can be used via the the or operator.
Examples
$stat_out := $(stat $file)[0]
# true, if $file is either a symlink or a directory
or $stat_out:is_symlink $stat_out:is_dir
# true, if $file is either a symlink or a directory
($stat_out.is_symlink or $stat_out.is_dir)
constants
global:constants
Language constants
control
global:control
Commands for flow control, (loops, etc)
The language's control-flow and process-execution builtins: conditionals and loops (if, match, while, loop, for), error handling (try, throw), job control (bg, fg, sleep, timeout), running external commands (cmd), and script-level utilities like source, which, and help itself. Imported into the global scope, so e.g. control:if and bare if are the same command -- in practice everything here is almost always written bare, since these are effectively the language's own keywords.
control:assert
control:assert condition=bool [message=string]
Error out if the condition is false.
Output
empty
This command accepts the following arguments:
conditionthe condition to check.message(default:"Assertion failed") the message to show if the condition is false.
Examples
assert (1 + 1 == 2)
assert ($x > 0) "x must be positive"
control:bg
control:bg job=integer
Resume a paused job, letting it continue running in the background.
Output
empty
Unlike a job started with a trailing & (which is in the background from the
moment it starts), bg acts on a job that already exists and is currently
paused (e.g. via crush:pause) -- it resumes it without putting it in the
foreground the way fg would.
This command accepts the following arguments:
jobthe job id of the paused job to resume in the background.
control:break
control:cmd
control:cmd command=file [<any>=any...] [arguments=any...]
Execute an external command
Output
binary_stream
Globs are file-expanded. Argument and switch order is preserved.
This command accepts the following arguments:
commandThe file path to the command to execute<any>=$anySwitches to pass in to the command. The name will be prepended with a double dash '--', unless it is a single character name, in which case a single dash '-' will be prependedargumentsArguments to pass in to the command
control:continue
control:continue
Break execution of the current iteration of a loop and continue to the next lap.
Output
empty
control:fg
control:fg [job=integer]
Return the output of a background pipeline
A job started with a trailing & runs in the background and registers its
eventual result for later retrieval; fg waits for and returns that result.
This command accepts the following arguments:
jobthe job id of the background job to put into the foreground.
Examples
# Create a pipe
$pipe := $($(table_input_stream value=$integer):pipe)
# Create a job that writes 100_000 integers to the pipe and put this job in the background
seq 100_000 | pipe:write &
# Create a second job that reads from the pipe and sums all the integers and put this job in the background
$sum_job_handle := $(pipe:read | sum &)
# Close the pipe so that the second job can finish
pipe:close
# Put the sum job in the foreground
fg $sum_job_handle
control:for
control:for [<any>=any...] body=command
Execute a command once for each element in a stream.
This command accepts the following arguments:
<any>=$anythe name to bind each element to, asname=stream(exactly one pair).bodythe block to execute once per element, with the bound name available as a variable.
Examples
# Iterate over the processes on the host
for i=$(host:procs) {
echo $("Iterating over process {}":format $i:name)
}
# Print ten messages
for i=$(seq to=10) {
echo $("Lap #{}":format $i)
}
# for is real grammar in expression mode too -- the loop variable is written
# with a $ sigil there (`for $i = ...`), not the bareword `name=stream` form
# command mode uses
assert (({
$sum := 0
for $i = $(seq 1 5) {
$sum = ($sum + $i)
}
$sum
}()) == 10)
control:help
control:help [topic=any] [format=string]
Show help on the specified value.
Output
empty
The help command will show you help about a thing that you pass in. If you,
for example pass in an integer (e.g. help 3), then you will see a help
message about how crush represents integers and what methods an integer
holds. You can also pass in any command to help (e.g. help $files for help
on the files command). Note that you will need to prepend the $ sigil to
the command name, since you're not using it as the command name.
If help's input is a pipeline, help shows help on the value in the
pipeline. Otherwise, if a topic argument is given, help shows help on that
value instead. With neither, help shows this introductory message.
This command accepts the following arguments:
topicthe topic you want help on.format(default:terminal, allowed:html,markdown,terminal) output format. The default,terminal, will render the help directly into the terminal. The other formats return a string containing either an html fragment or markdown.
Examples
# Show this message
help $help
# Show help on the root namespace
help $global
control:if
control:if condition=bool true_clause=command [else=string] [false_clause=command]
Conditionally execute a command once.
This command accepts the following arguments:
conditionthe condition to filter on.true_clausethe command to invoke if the condition is true.false_clausethe (optional) command to invoke if the condition is false.
Examples
if ($a > 10) {
echo big
} else {
echo small
}
# if is real grammar in expression mode too, with the exact same syntax
assert ((if ($a > 10) { "big" } else { "small" }) == "big")
control:loop
control:loop body=command
Repeatedly execute the body until the break command is called.
Output
empty
This command accepts the following arguments:
bodythe command to repeatedly invoke.
Examples
loop {
if $(i_am_tired) {
break
}
echo Working
}
# loop is real grammar in expression mode too, with the exact same syntax
assert (({
$i := 0
$sum := 0
loop {
if ($i >= 5) { break }
$sum = ($sum + $i)
$i = ($i + 1)
}
$sum
}()) == 10)
control:match
control:match subject=any body=command
Branch on a value against a sequence of cases.
The body is a block containing a sequence of arms, where each arm is one of:
case <value> {<body>}matches if the subject equals<value>.any <stream> {<body>}matches if the subject equals any individual value produced by reading<stream>(e.g.$(seq 5 10)or a list).is <type> {<body>}matches if the subject's type is<type>.default {<body>}always matches.
Arms are tried in order; the first one that matches runs, and the rest are
skipped. If nothing matches, match errors.
This command accepts the following arguments:
subjectthe value to match against.bodya block containing the match's arms.
Examples
match $x {
case 2 {echo "$x is 2"}
any $(seq 5 10) {echo "$x is between 5 and 10"}
is $string {echo "$x is a string"}
default {echo "I don't know what $x is"}
}
# match is real grammar in expression mode too, with the exact same syntax
assert ((match $x {
case 2 {"two"}
any $(seq 5 10) {"between 5 and 10"}
is $string {"a string"}
default {"something else"}
}) == "two")
control:return
control:return [value=any]
break execution of a closure command and optionally return a value.
The return command can only be used when inside of a closure command. Closure blocks can not break early using the return command. Do note that you can use the return command inside of a closure block which is nested arbitrarily deeply inside of a closure command, which will stop execution of all inner blocks and return the closure command.
This command accepts the following arguments:
valuethe value to return
Examples
# Define a factorial command
$factorial := {
|$number: $integer|
if ($number == 1) {
return 1
} else {
return ($number * factorial($number - 1))
}
}
# Call the command
factorial 5
control:schedule
control:schedule interval=duration [initial_delay=duration] [command=command] [--schedule_at_fixed_rate] [--once]
Schedule events at specified time intervals
If a command is specified, timer will run the command at the specified cadence.
If timer is used inside a pipeline, it will read one row of input at the specified cadence and write it out again.
Otherwise, timer will simply write an empty row at the specified cadence.
If a command fails, the timer will stop.
This command accepts the following arguments:
intervalthe interval between heartbeats.initial_delaythe delay for the first heartbeat. If no initial delay is specified, use the interval parameter.commanda command to run at each heartbeat.schedule_at_fixed_rate(default:false) if heart beat delivery starts blocking, catch up by sending more heartbeats afterwards.once(default:false) only schedule a single heartbeat. After that, exit.
Examples
# Show one row of the pipeline output every second
files / --recurse | schedule $(duration:of seconds=1)
# Wait for a second and then print hello once
schedule $(duration:of seconds=1) command={ echo hello } --once
control:sleep
control:sleep duration=duration
Pause execution of commands for the specified amount of time
This command accepts the following arguments:
durationthe time to sleep for.
Examples
sleep $(duration:of seconds=10)
control:source
control:throw
control:throw error_type=string message=string
Raise a custom error, catchable and discriminable by its own error type.
Output
empty
Unlike every other error in Crush, a thrown error's type (as seen via
catch {|$e| ...}'s $e:type) is error_type itself, not a fixed name tied
to whatever went wrong internally -- so a script or library can define and
catch its own error categories.
This command accepts the following arguments:
error_typethe error's type, e.g. "NotFound". Visible to a catch block as$e:type.messagethe error's message. Visible to a catch block as$e:message.
Examples
try { throw "NotFound" "no such user" } catch {|$e| assert ($e:type == "NotFound")}
control:timeit
control:timeit it=command [number=integer] [repeat=integer]
Execute a command many times and estimate the execution time.
This command accepts the following arguments:
itthe command to time.numberthe number of runs in each repeat. If unspecified, timeit will repeat enough times for each batch to take roughly 0.4 seconds.repeat(default:5) repeat count. The average speed in the fastest repeat will be returned.
Examples
timeit {files|sort size}
control:timeout
control:timeout duration=duration command=command
Run a command, terminating it if it hasn't finished within the given duration.
If command finishes before duration elapses, timeout returns its result
normally. Otherwise, a termination signal is sent to it -- the same cooperative
mechanism crush:terminate uses, which only a command that actually checks for
it (like sleep) will actually stop for; most builtins don't, and will keep
running in the background regardless -- and timeout itself fails with a
timeout error.
A command left running this way isn't just background noise: crush waits for
every spawned thread to finish before the whole session exits, so a command
that never cooperates and never finishes on its own (an infinite loop, for
example) will keep the script -- or the whole interactive session -- from
exiting cleanly, even though timeout itself already returned its error.
This command accepts the following arguments:
durationhow long to let the command run before terminating it.commandthe command to run.
Examples
timeout $(duration:of seconds=5) {sleep $(duration:of seconds=30)}
control:timer
control:timer it=command
Execute a command once and return the execution time.
Output
duration
This command accepts the following arguments:
itthe command to time.
Examples
timer {files|sort size}
control:try
control:try body=command [catches=any...]
Execute a command, recovering from any error it produces.
If body fails, execution of body stops at the failing statement. Zero or
more catch <filter>? {...} clauses may follow body, each the literal word
catch, an optional filter (a string, glob, or regex -- anything implementing
__is__, same as like/=~/match's is arm), and a block.
On failure, clauses are tried in order; the first one whose filter matches the
error's type field (see below) -- or that has no filter at all -- runs, and
the rest are skipped. Its block receives a struct describing the error as its
single unnamed argument: message (the error text), type (the internal error
variant's name, e.g. IOError, or a custom type set via throw), and
command (the name of the command that failed, if known -- empty otherwise).
If no clause's filter matches, the error propagates normally, exactly as if
try had no catch clauses of its own. With no catch clauses at all, an error
is recovered from silently -- execution continues normally with whatever comes
after try.
This command accepts the following arguments:
bodythe command to attempt.catcheszero or morecatch <filter>? {...}clauses: the literal wordcatch, an optional filter pattern, and a block to run if that filter matches the error'stype(or always, if no filter is given).
Examples
try {
risky:command
} catch {
|$error| echo ("Recovered: {}":format($error:message))
}
try {
risky:command
} catch ^(Serde) {
|$e| echo ("Serialization error: {}":format($e:message))
} catch Dns* {
|$e| echo ("DNS error: {}":format($e:message))
}
# try/catch is real grammar in expression mode too, with the exact same syntax
# -- except a glob filter like Dns* above needs $(...) there, since glob literals
# only parse in command mode
assert ((try {
throw("DnsTimeout", "no response")
} catch ^(Serde) {
|$e| "serde"
} catch $(Dns*) {
|$e| "dns"
}) == "dns")
control:which
control:which command=string
Find the path of an executable
Output
file
which searches the directories of the $crush:end[PATH] enivornment variable list for the specified command and returns the path to the first match.
This command accepts the following arguments:
commandthe name of the command to find.
Examples
# Returns '/bin/ps'
which ps
control:while
control:while condition=command [body=command]
Repeatedly execute the body for as long the condition is met.
Output
empty
The loop body is optional. If not specified, the condition is executed until it returns false. This effectively means that the condition becomes the body, and the loop break check comes at the end of the loop.
This command accepts the following arguments:
conditionthe condition.bodythe command to invoke as long as the condition is true.
Examples
while {./some_file:exists} {echo "hello"}
# while is real grammar in expression mode too -- the condition is a bare
# expression there, not wrapped in its own {...} block like in command mode
assert (({
$i := 0
$sum := 0
while ($i < 5) {
$sum = ($sum + $i)
$i = ($i + 1)
}
$sum
}()) == 10)
crush
global:crush
Information about this Crush session
The crush namespace holds state and controls for the running Crush process itself, as distinct from state about the external world (host) or the data flowing through a pipeline. This is where you configure the prompt and title, the warning log and syntax highlighting, read and write OS environment variables, inspect running jobs and threads, and control how the shell exits. See docs/config.md for a guided tour of what's configurable here.
crush:exit
crush:exit [status=integer] [--force]
Exit the shell
Output
empty
If other jobs are still running, exit fails with an error unless force is
set, in which case those jobs are terminated first.
This command accepts the following arguments:
status(default:0) The exit status to set for the processforce(default:false) Terminate all running jobs
crush:history
crush:history
List previous commands
Output
table_input_stream idx=$integer command=$string
All previous invocation
crush:jobs
crush:jobs
List running jobs
Output
table_input_stream id=$integer parent=$any description=$string type=$string status=$string
All currently running jobs
crush:language_mode
crush:language_mode
Returns the current language mode, either command or expression.
Output
string
Command mode is the default mode.
crush:pause
crush:pause jid=integer
Pause the given job.
Output
empty
This command accepts the following arguments:
jidThe job id for the job to pause
crush:resume
crush:resume jid=integer
Resume the given job.
Output
empty
This command accepts the following arguments:
jidThe job id for the job to resume
crush:run_mode
crush:run_mode
Returns how crush is currently running, either interactive or non-interactive.
Output
string
In interactive mode, the prompt is shown and commands are entered interactively with access to history, keyboard shortcuts, etc. In non-interactive mode, no prompt is shown and commands are read from a file. The run mode can not be changed while crush is running. It is decided by how crush was started.
crush:terminate
crush:terminate jid=integer
Terminate the given job.
Output
empty
A job may continue running for some time after receiving a termination notification. Output pipelines produced by the job will still be readable and will contain any buffered IO already sent to the job before it received the termination notification.
This command accepts the following arguments:
jidThe job id for the job to terminate
Examples
# Create a job that produces a lot of output
$all_files := $(files --recurse /)
# Read a few lines of output
$all_files | head
# Find the job id of the job we want to terminate
crush:jobs
# Ask the job to terminate.
crush:terminate 1
# This will output the number of buffered rows that were buffered
$all_files | count
crush:threads
crush:threads
All the subthreads crush is currently running.
Output
table_input_stream job_id=$integer command_id=$integer created=$time name=$string
crush:byte_unit
global:crush:byte_unit
Formating style for table columns containing byte sizes.
crush:byte_unit:get
crush:byte_unit:list
crush:byte_unit:set
crush:byte_unit:set byte_unit=string
Set the current byte unit.
Output
empty
This command accepts the following arguments:
byte_unitthe new byte unit.
crush:env
global:crush:env
Environment variables
crush:locale
global:crush:locale
Locale data for Crush
crush:locale:get
crush:locale:list
crush:locale:set
crush:locale:set locale=string
Set the current locale.
Output
empty
This command accepts the following arguments:
localethe new locale.
crush:prompt
global:crush:prompt
Prompt data for Crush
crush:prompt:get
crush:prompt:get
Get the current prompt command.
crush:prompt:set
crush:prompt:set [prompt=command]
Set a new prompt command.
Output
empty
This command accepts the following arguments:
promptThe new command to invoke in order to produce a prompt
crush:title
global:crush:title
Title data for Crush
crush:title:get
crush:title:get
Get the current title command
crush:title:set
crush:title:set [title=command]
Set a new title command
Output
empty
This command accepts the following arguments:
titleThe new command to invoke in order to produce a title
crush:warn
global:crush:warn
Warnings reported by commands that experienced a partial failure
crush:warn:list
crush:warn:list
List recent warnings reported by commands that experienced a partial failure.
Output
table_input_stream timestamp=$time command=$string message=$string file=$string location=$string
Commands that continue past a partial failure (e.g. one bad row out of a
stream) report it as a warning rather than aborting. A bounded number of the
most recent warnings are kept here (see crush:warn:limit); in interactive
mode, they are also printed as soon as they happen, unless disabled (see
crush:warn:print).
crush:warn:new
crush:warn:new message=string
Report a warning to the bounded log crush:warn:list keeps.
Output
empty
Every builtin that presses on past a partial failure (each/where/group/files, and others) reports it through this exact same mechanism instead of aborting; this is that mechanism made directly callable, for a script or closure that wants to flag something without stopping.
This command accepts the following arguments:
messagethe warning message to report.
Examples
crush:warn:new "something looked off, continuing anyway"
crush:warn:limit
global:crush:warn:limit
How many warnings crush:warn:list keeps before evicting the oldest
crush:warn:limit:get
crush:warn:limit:get
Get how many warnings crush:warn:list keeps before evicting the oldest.
Output
integer
crush:warn:limit:set
crush:warn:limit:set limit=integer
Set how many warnings crush:warn:list keeps before evicting the oldest.
Output
empty
This command accepts the following arguments:
limitthe new warning limit.
crush:warn:print
global:crush:warn:print
Whether warnings are printed to the screen as they happen
crush:warn:print:get
crush:warn:print:set
crush:warn:print:set print=bool
Set whether warnings are printed to the screen as they happen.
Output
empty
Only takes effect in interactive mode -- a warning is always recorded in
crush:warn:list either way, this only controls whether it's also printed
immediately. Defaults to true.
This command accepts the following arguments:
printwhether to print warnings to the screen as they happen.
Examples
crush:warn:print:set $false
dns
global:dns
DNS querying and metadata
DNS, the Domain Name System (https://en.wikipedia.org/wiki/Domain_Name_System), is the internet's distributed naming system -- it translates human-readable domain names like example.com into the numeric IP addresses computers actually use to connect to each other, along with a handful of other record types (mail servers, text records, service discovery, ...).
It's hierarchical and distributed rather than a single lookup table: no one server holds every record. A name is resolved by delegating from root servers down through top-level-domain servers to the domain's own authoritative servers, though in practice a query is usually answered by a caching resolver (see dns:nameserver) long before it needs to walk that whole chain.
dns:domain
dns:domain
DNS domain, if any
Output
any
Reads the local domain configured in /etc/resolv.conf's domain line, if
any -- no network query is made. Returns $empty if none is configured.
dns:nameserver
dns:nameserver
List of default nameservers
Reads the nameservers configured in /etc/resolv.conf -- no network query
is made. This is exactly what dns:query/dns:query_reverse themselves fall
back to when their own nameserver argument is left unset (specifically, the
first one listed).
dns:query
dns:query name=string [record_type=string] [--tcp] [nameserver=string] [port=integer] [--no_follow_cname] [timeout=duration]
Look up a DNS record
The columns of the returned table depend on record_type:
A,AAAA,NS,PTR, andCNAME:target(string) andttl(duration)MX:target,preference(integer), andttlSRV:target,priority,weight,port(all integer), andttlTXT:text(binary) andttlSOA:mname,rname(strings),serial(integer), andrefresh,retry,expire, andttl(all durations)
If a response's first answer is a CNAME record, it's followed
transparently and the query is retried against the alias's target -- up to 8
hops, after which a chain that still hasn't resolved is a hard error rather
than being followed forever (a spoofed or compromised nameserver could
otherwise cause unbounded recursion, since plain UDP DNS has no cryptographic
integrity). Set no_follow_cname=$true, or query for the CNAME record type
directly, to see the alias itself instead of following it.
If nameserver isn't given, the first nameserver listed in
/etc/resolv.conf is used (see dns:nameserver). name is always looked up
exactly as given -- unlike most system resolvers, this does not consult
/etc/resolv.conf's search domains (see dns:search_paths) to expand an
unqualified name.
This command accepts the following arguments:
nameDNS record to look up.record_type(default:A, allowed:A,AAAA,CNAME,MX,NS,PTR,SOA,SRV,TXT) DNS record type.tcp(default:false) use TCP as the transport instead of UDP.nameserverthe nameserver to talk to. If none is given, use the nameservers configured in/etc/resolv.conf.port(default:53) port to talk to the nameserver on.no_follow_cname(default:false) if a CNAME record is encountered, do not follow it. Show the actual CNAME record instead.timeout(default:5s) connection timeout.
Examples
dns:query "www.google.com" AAAA
dns:query "example.com" MX
# See the alias itself instead of transparently following it
dns:query "www.example.com" CNAME
dns:query_reverse
dns:query_reverse address=string [--tcp] [nameserver=string] [port=integer] [timeout=duration]
Perform a reverse DNS lookup on a given IP address
Looks up the hostname associated with address via a PTR record,
automatically building the reverse-lookup name DNS uses for this (e.g. under
in-addr.arpa for IPv4, ip6.arpa for IPv6) -- address should be given as
a plain, forward IP address, not already reversed. Returns the hostname as a
plain string, or nothing if no PTR record exists for that address. Unlike
dns:query, this never follows a CNAME; a reverse zone is not expected to
contain one.
This command accepts the following arguments:
addressIP address to look up. Can be either IPv4 or IPv6.tcp(default:false) Use TCP connection instead of UDPnameserverOverride the nameserver to talk toport(default:53) DNS porttimeout(default:5s) Connection timeout.
Examples
dns:query_reverse "127.0.0.1"
dns:search_paths
dns:search_paths
List of DNS search paths
Reads the DNS search domains configured in /etc/resolv.conf -- no network
query is made. A system resolver normally appends these, in order, to an
unqualified hostname before giving up (e.g. trying host.example.com when
asked to resolve plain host); dns:query does not apply this itself --
name is always looked up exactly as given.
fs
global:fs
File system functionality
Commands for working with the filesystem: listing and stat-ing files (files, stat), changing directory (cd), computing disk usage (usage), listing mount points (mounts), and watching a path for changes (watch). Imported into the global scope, so e.g. fs:cd and bare cd are the same command.
fs:cd
fs:cwd
fs:files
fs:files [directory=one_of $string $file $glob $re...] [--recurse] [permissions=bool] [--inode] [links=bool] [user=bool] [group=bool] [size=bool] [--blocks] [modified=bool] [--accessed] [type=bool] [file=bool]
Show information about files and directories
If given no arguments, list the contents to the current working directory. If given any unnamed arguments, those will be the files and directories to list.
By default, files will not recurse into subdirectories. You can override this using
the --recurse switch.
This command accepts the following arguments:
directorydirectories and files to listrecurse(default:false) recurse into subdirectoriespermissions(default:true) show permissionsinode(default:false) show inode numberlinks(default:true) show link countuser(default:true) show usernamegroup(default:true) show group namesize(default:true) show file sizeblocks(default:false) show block countmodified(default:true) show modification timeaccessed(default:false) show time of last file accesstype(default:true) show file typefile(default:true) show file name
fs:mounts
fs:mounts
List filesystem mount points
Output
table_input_stream size=$integer available=$integer usage=$float format=$string readonly=$any name=$string path=$file
mounts outputs the following information about each mount point:
sizesize in bytes.availableavailable space in bytes.usageusage percentage.formatfilesystem type (ntfs, ext4, etc.).readonlywhether the filesystem is mounted readonly.namename assigned to this mountpoint, if any.paththe mount location.
fs:stat
fs:stat [destination=one_of $string $file $glob $re...] [--symlink]
Return a row with information about each file
Output
table_input_stream is_socket=$bool is_symlink=$bool is_file=$bool is_block=$bool is_dir=$bool is_char=$bool is_fifo=$bool inode=$integer nlink=$integer uid=$integer gid=$integer size=$integer block_size=$integer blocks=$integer access_time=$time modification_time=$time creation_time=$time file=$file
The return value contains the following columns:
is_socket(bool) is the file is a socketis_symlink(bool) is the file a symbolic linkis_block(bool) is the file a block deviceis_dir(bool) is the file is a directoryis_char(bool) is the file a character_deviceis_fifo(bool) is the file a fifoinode(integer) the inode number of the filenlink(integer) the number of hardlinks to the fileuid(integer) The user id of the file ownergid(integer) The group id of the file ownersize(integer) File size in bytesblock_size(integer) The size of a single block on the device storing this fileblocks(integer) The number of blocks used to store this fileaccess_time(time) The last time this file was accessedmodification_time(time) The last time this file was modifiedcreation_time(time) The time this file was createdfile(path) The filename
This command accepts the following arguments:
destinationthe files to show the status for.symlink(default:false) stat symlinks, not the files they point to.
fs:usage
fs:usage [directory=one_of $string $file $glob $re...] [--silent] [--all]
Calculate the recursive directory space usage.
Output
table_input_stream size=$integer blocks=$integer file=$file
This command accepts the following arguments:
directorythe files to calculate the recursive size of.silent(default:false) do not show directory sizes for subdirectories.all(default:false) write sizes for all files, not just directories.
fs:watch
fs:watch path=one_of $string $file $glob $re [--recurse]
Watch a path for filesystem changes and stream them as rows.
Output
table_input_stream path=$file kind=$string timestamp=$time
Uses the operating system's native filesystem notification API (inotify on Linux, FSEvents on macOS, ReadDirectoryChangesW on Windows), so what counts as a change and how quickly it is reported is a best-effort property of the host OS, not a cross-platform guarantee -- rapid changes may be coalesced, and exact granularity differs by platform.
This command accepts the following arguments:
paththe path to watch.recurse(default:false) also watch subdirectories.
Examples
fs:watch . --recurse | where {kind == "Create(File)"}
groups
global:groups
User group commands
Commands for querying user groups on this system -- groups:list for every group and its gid, and lookup by name via groups[name]. Sibling to users, but for groups rather than individual accounts.
grpc
global:grpc
gRPC connection
grpc:connect
grpc:connect host=string @ $(one_of $string $glob $re) [--plaintext] [timeout=duration] [port=integer]
Create a connection to a gRPC service.
gRPC (https://grpc.io) is Google's open-source, high-performance RPC framework, built on HTTP/2 and Protocol Buffers.
To send RPC calls to a server, you must first create a grpc connection, writing something like $conn := $(grpc:connect host=localhost service=* --plaintext).
The resulting connection struct will have one method for each endpoint on the chosen services of the host you connected to. When calling a method, there are two different ways to pass in input parameters.
If you want to pass exactly one message to the endpoint, e.g. because the endpoint does not use client streaming, you have the option of passing the fields of the message as arguments to the method call, e.g. $conn:ReverseString input=hello.
The grpc methods support tab completion of argument names. They also come with help messages (e.g. help $conn:ReverseString) that describes the input and output format.
If you want to pass multiple messages to the endpoint, you must do so by piping in a table_input_stream, where the column names of the stream are identical to the field names of the message, e.g. list:of foo bar baz | select input={$value} | $conn:ReverseString
Output from a gRPC method call is always a $table_input_stream, with one row per message. If an endpoint does not use server side streaming, the output always has one row.
Once you are done with a gRPC connection, you should close it to free up resources. Do so by calling the close method, e.g. $conn:close.
This command accepts the following arguments:
hostthe host to connect to.servicethe service to connect to on this host. This can be a string, a glob or a regular expression, in order to allow you to easily specify multiple services, e.g. use*to connect to all available services.plaintext(default:false) use plaintext instead of TLS to connect.timeout(default:5s) the timeout for making calls.port(default:50051) the port to connect to.
Examples
$conn := $(grpc:connect host=localhost service=* --plaintext)
# Returns "olleh"
$conn:ReverseString input="hello"
# Returns a stream with the values "oof", "rab", and "zab"
list:of foo bar baz | select input={$value} | $conn:ReverseString
# Close the connection once you're done
$conn:close
host
global:host
Information about the host this crush session is running on
Information about the machine this Crush session is running on: memory, battery, uptime, process and thread tables, and (nested further) host:os and host:cpu for operating-system and CPU-specific metadata. Contrast with crush, which is about the Crush process itself, not the machine underneath it.
host:battery
host:memory
host:memory
memory usage of this host.
Output
struct
The output struct contains the following fields:
total, total amount of memory available to the host
free, unused memory
avail, available memory
swap_total, total amount of swap available to the host
swap_free, unused swap
host:name
host:procs
host:procs
Return a table stream containing information on all running processes on this host
Output
table_input_stream pid=$integer ppid=$integer user=$string rss=$integer vms=$integer cpu=$duration name=$string
host:procs accepts no arguments.
host:signal
host:signal [pid=integer...] [signal=string]
Send a signal to a set of processes
Output
empty
The set of existing signals is platform dependent, but common signals include SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT and SIGWINCH.
This command accepts the following arguments:
pidthe id of the process to send to.signal(default:SIGTERM) the name of the signal to send.
Examples
# Create a `killall` command that kills any process whose name matches the specified pattern
# The pattern can be a an exact string, a wildcard, or a regex
$killall := { |$victim| host:signal @$(host:procs|where {$name =~ $victim}|select pid | list:collect) signal=SIGKILL}
# Kill all crush commands
killall ^(crush)
host:threads
host:threads
Return a table stream containing information on all running threads on this host
Output
table_input_stream tid=$integer pid=$integer priority=$integer user=$duration system=$duration name=$string
host:threads accepts no arguments.
host:uptime
host:cpu
global:host:cpu
Metadata about the CPUs of this host
host:cpu:arch
host:cpu:count
host:cpu:load
host:os
global:host:os
Metadata about the operating system this host is running
host:os:name
host:os:version
io
global:io
Data serialization I/O
Reading and writing structured data in specific wire formats -- json, yaml, toml, csv, hex, base64, and percent encoding, and Crush's own native pup format, each its own to/from pair. Also home to a few general-purpose I/O commands that don't belong to any one format: http, echo, readline, and member/members for pulling data out of a struct or stream. Imported into the global scope, so e.g. io:json:from and bare json:from are the same command.
io:dir
io:dir [value=any]
List the member names of a value.
Output
list $string
Works on any value -- a struct's own fields, a scope's local variables, or
(for anything else, including a type value like $float) the methods its
type declares.
If dir's input is a pipeline, dir lists the members of the value in the
pipeline. Otherwise, dir requires a value to be provided as an argument,
and lists the members of that value instead.
Pair with member to fetch one of the listed names -- member's own name
argument, unlike the : operator, can be a runtime value instead of a fixed
word in the source, so the two together let you enumerate and read members
whose names aren't known ahead of time.
This command accepts the following arguments:
valuethe value to list the members of.
Examples
dir .
# The full help text of every method float has
dir $float | each {|$name| help ($float | member $name)}
io:echo
io:echo [values=any...] [--raw]
Prints all arguments directly to standard output.
Output
empty
If no arguments are passed to the values parameter, print the input pipeline value instead.
This command may at first appear pointless, since values entered on the prompt are printed to standard output by default. But that is only true when running a command interactively. When executing a file or running a closure, results are either completely ignored or returned as the return value of the block. In these situations, the echo command is useful for making sure a given value is written to standard output.
This command accepts the following arguments:
valuesthe values to print.raw(default:false) do not escape control characters in string values.
Examples
# These command invocations are equivalent
echo "Hello, world!"
"Hello, world!" | echo
io:http
io:http uri=string [method=string] [form=one_of $file $string $binary $binary_input_stream $glob $re] [header=string...] [timeout=duration]
Make a http request
Returns a struct with the following fields:
status_code(integer) the http status code of the replystatus_name(string) the name associated with the http status codeheader(list) the http headers of the replybody(binary_stream) the content of the reply
The http status codes and corresponding names are defined in https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
This command accepts the following arguments:
uriURI to requestmethod(default:GET, allowed:GET,POST,PUT,DELETE,HEAD,OPTIONS,CONNECT,PATCH,TRACE) the HTTP method to use in this request.formform content, if any.headerHTTP headers, must be on the form "key:value".timeout(default:5s) connection timeout.
Examples
http "https://example.com/" header=$("Authorization: Bearer {}":format $token)
io:member
io:member field=string [value=any]
Extract one named member from a value.
Works like the : member operator, except the member name is a runtime
value (e.g. a variable) rather than a fixed word in the source -- use this
when the name to look up isn't known until the script runs. Pair with dir
to discover a value's member names first.
If member's input is a pipeline, member extracts the named member from
the value in the pipeline. Otherwise, member requires a value to be
provided as an argument, and extracts the named member from that value
instead.
This command accepts the following arguments:
fieldthe member to extract.valuethe value to extract the member from.
Examples
$uri := "https://raw.githubusercontent.com/liljencrantz/crush/refs/heads/master/example_data/dinosaurs.json"
http $uri | member body | json:from
# member also takes its value as an argument instead of a pipe
member __neg__ 5
# dir lists a value's member names; member fetches one by name -- together
# they let you enumerate members whose names aren't known ahead of time
for name=$(dir 5) { echo (member $name 5) }
io:members
io:members
List the columns of any streamable input value as name/type pairs.
Output
table_input_stream name=$string type=$type
Works on anything that can be read as a stream of rows -- a table, a list, a dict, a struct, a scope -- and reports that stream's shape without consuming any of its actual rows.
Examples
$my_dict | members
io:readline
io:readline [prompt=string] [history=string]
Read a string of input from the user.
Output
string
The readline command uses the same keyboard shortcuts as crush itself uses internally.
This command accepts the following arguments:
prompt(default:"crush# ") the prompt to show the user.historyload and save history under specified name.
Examples
# Ask the user for their name
echo "What is your name?"
$name := $(readline prompt="name: ")
echo $("Hello, {}!":format $name)
io:val
io:val value=any
Return value
Output
any
This command is useful if you want to pass a command as input in a pipeline instead of executing it. It is different from the echo command in that val sends the value through the pipeline, whereas echo prints it to screen.
This command accepts the following arguments:
valuethe value to pass as output.
Examples
val $val
io:base64
global:io:base64
Base64 conversions
io:base64:from
io:base64:from [files=one_of $file $string $binary $binary_input_stream $glob $re...] [alphabet=string]
Read a Base64 value and decode it.
Output
binary_stream
If no file is specified, use the input, which must be a binary or a string.
The standard alphabet follows RFC 4648, and uses a-z, A-Z, 0-9, +, and /. The urlsafe alphabet uses a-z, A-Z, 0-9, -, and .. Both use = for padding.
This command accepts the following arguments:
filesthe files to read from. Read from input if no file is specified.alphabet(default:standard) base64 encoding style to use.
Examples
# Will output hello, world!
"aGVsbG8sIHdvcmxkIQ==" | base64:from
io:base64:to
io:base64:to [file=one_of $string $file $glob $re] [alphabet=string]
Write specified binary or string as Base64
Output
binary_stream
If no file is specified, produce a binary stream as output.
The standard alphabet follows RFC 4648, and uses a-z, A-Z, 0-9, +, and /. The urlsafe alphabet uses a-z, A-Z, 0-9, -, and .. Both use = for padding.
This command accepts the following arguments:
filethe file to write to. Write to output if no file is specified.alphabet(default:standard) base64 encoding style to use.
Examples
# Will output aGVsbG8sIHdvcmxkIQ==
"hello, world!" | base64:to
io:bin
global:io:bin
Binary data I/O
io:bin:from
io:bin:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Read specified files (or input) as a binary stream
If no file is specified, the input must be either binary or a string which will be converted to a binary using utf-8.
This command accepts the following arguments:
filessource to read from. If unspecified, will read from input, which must be astring,binaryorbinary_stream.
io:bin:to
io:csv
global:io:csv
CSV I/O
io:csv:from
io:csv:from [files=one_of $file $string $binary $binary_input_stream $glob $re...] [<any>=type...] [separator=string] [head=integer] [trim=string]
Parse specified files as CSV files
This command accepts the following arguments:
filessource. If unspecified, will read from input, which must be a binary or binary_stream.<any>=$typename and type of all columns.separator(default:',') column separator.head(default:0) skip this many lines of input from the beginning.trimtrim this character from start and end of every value.
Examples
csv:from separator="," head=1 name=$string age=$integer nick=$string
io:hex
global:io:hex
Hexadecimal conversions
io:hex:from
io:hex:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Read a hexadecimal value and decode it.
Output
binary_stream
If no file is specified, use the input, which must be a binary or a string.
This command accepts the following arguments:
filesthe files to read from (read from input if no file is specified).
Examples
"68656c6c6f2c20776f726c6421" | hex:from
io:hex:to
io:hex:to [file=one_of $string $file $glob $re]
Write specified binary or string as hexadecimal
Output
binary_stream
If no file is specified, produce a binary stream as output.
This command accepts the following arguments:
filedestination file to write to. If unspecified, output is returned as abinary_stream.
Examples
"hello, world!" | hex:to
io:json
global:io:json
JSON I/O
io:json:from
io:json:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Parse json format
When deserializing a list, json:from will try to infer the type of the list. If all of the elements of the list are of the same type, the list will be parametrized to the same type. If all elements are objects, and all objects have the same set of fields with the same types, the list will be turned into a table.
This command accepts the following arguments:
filessource to read from. If unspecified, will read from input, which must be astring,binaryorbinary_stream.
Examples
http "https://jsonplaceholder.typicode.com/todos/3"| member body | json:from
io:json:to
io:json:to [file=one_of $string $file $glob $re] [--compact]
Serialize to json format
When serializing a list, some types have to be squashed, because json does not have all the same types that Crush does:
timevalues are turned into strings in the RFC 3339 format.durationvalues are turned into the integer number of seconds in the duration.
This command accepts the following arguments:
filedestination file to write to. If unspecified, output is returned as abinary_stream.compact(default:false) Disable line breaking and indentation.
Examples
files | json:to
io:lines
global:io:lines
Line based I/O
io:lines:from
io:lines:from [files=one_of $file $string $binary $binary_input_stream $glob $re...] [--skip_empty_lines] [--strip_whitespace]
Read specified files (or input) as a table with one line of text per row
Output
table_input_stream line=$string
This command accepts the following arguments:
filesthe files to read from (read from input if no file is specified).skip_empty_lines(default:false) do not emit empty lines.strip_whitespace(default:false) strip whitespace from beginning and end of lines.
io:lines:to
io:lines:to [file=one_of $string $file $glob $re]
Write specified stream of strings to a file (or convert to BinaryStream) separated by newlines
This command accepts the following arguments:
filedestination file to write to. If unspecified, output is returned as abinary_stream.
io:percent
global:io:percent
Percent-encoding (URL-style) conversions
io:percent:from
io:percent:from [input=string]
Decode a percent-encoded string.
Output
string
Replaces every %XX escape with the byte it represents. Errors if the
decoded bytes aren't valid UTF-8.
This command accepts the following arguments:
inputthe percent-encoded string to decode. Reads a string from input if unspecified.
Examples
# Returns "a b/c"
percent:from "a%20b%2Fc"
io:percent:to
io:percent:to [input=string]
Percent-encode a string for safe use in a URL.
Output
string
Escapes every byte except the RFC 3986 unreserved set -- ASCII letters,
digits, and -_.~ -- as %XX. This is the strictest common encoding, safe to
use for a single path segment, query key, or query value. It does escape /
and &, so don't apply it to an already-assembled path or query string, only
to one component of one.
This command accepts the following arguments:
inputthe string to percent-encode. Reads a string from input if unspecified.
Examples
# Returns "a%20b%2Fc"
percent:to "a b/c"
io:pup
global:io:pup
Pup I/O
io:pup:from
io:pup:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Parse pup format
This command accepts the following arguments:
filessource to read from. If unspecified, will read from input, which must be astring,binaryorbinary_stream.
Examples
pup:from serialized.pup
io:pup:to
io:pup:to [file=one_of $string $file $glob $re]
Serialize to pup format
Pup is the native crush serialization format. All Crush types, including lambdas can be serialized to this format.
This command accepts the following arguments:
filedestination file to write to. If unspecified, output is returned as abinary_stream.
Examples
files | pup:to
io:split
global:io:split
Configurable word splitting I/O
io:split:from
io:split:from [files=one_of $file $string $binary $binary_input_stream $glob $re...] separator=string [trim=string] [--allow_empty]
Read specified files (or input) as a table, split on the specified separator characters.
This command accepts the following arguments:
filesthe files to read from (read from input if no file is specified).separatorcharacters to split ontrimcharacters to trim from start and end of each token.allow_empty(default:false) allow empty tokens.
io:toml
global:io:toml
TOML I/O
io:toml:from
io:toml:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Parse toml format
Input can either be a binary stream or a file. All Toml types except datetime are supported. Datetime is not supported because the rust toml library currently doesn't support accessing the internal state of a datetime.
When deserializing a list, toml:from will try to infer the type of the list. If all of the elements of the list are of the same type, the list will be parametrized to the same type. If all elements are objects, and all objects have the same set of fields with the same types, the list will be turned into a table.
This command accepts the following arguments:
filessource to read from. If unspecified, will read from input, which must be astring,binaryorbinary_stream.
Examples
toml:from Cargo.toml
io:toml:to
io:toml:to [file=one_of $string $file $glob $re]
Serialize to toml format
If no file is specified, output is returned as a BinaryStream. The following Crush types are supported: File, string, integer, float, bool, list, table, table_input_stream, struct, time, duration, binary and binary_stream.
When serializing a list, some types have to be squashed, because toml does not have all the same types that Crush does:
timevalues are turned into strings in the RFC 3339 format.durationvalues are turned into the integer number of seconds in the duration.
This command accepts the following arguments:
filedestination file to write to. If unspecified, output is returned as abinary_stream.
Examples
$(files)[0] | toml:to
io:words
global:io:words
Word splitting I/O
io:words:from
io:words:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Read input and split on word boundaries.
Input can be files or the input pipe, which must be a binary input stream, split on word boundaries, trim away punctuation and discard empty "words".
This command accepts the following arguments:
filesthe files to read from (read from input pipe if no file is specified).
io:yaml
global:io:yaml
YAML I/O
io:yaml:from
io:yaml:from [files=one_of $file $string $binary $binary_input_stream $glob $re...]
Parse yaml format
When deserializing a list, yaml:from will try to infer the type of the list. If all of the elements of the list are of the same type, the list will be parametrized to the same type. If all elements are objects, and all objects have the same set of fields with the same types, the list will be turned into a table.
This command accepts the following arguments:
filessource to read from. If unspecified, will read from input, which must be astring,binaryorbinary_stream.
Examples
(http "https://jsonplaceholder.typicode.com/todos/3"):body | yaml:from
io:yaml:to
io:yaml:to [file=one_of $string $file $glob $re]
Serialize to yaml format
When serializing a list, some types have to be squashed, because yaml does not have all the same types that Crush does:
timevalues are turned into strings in the RFC 3339 format.durationvalues are turned into the integer number of seconds in the duration.
This command accepts the following arguments:
filedestination file to write to. If unspecified, output is returned as abinary_stream.
Examples
files | yaml:to
math
global:math
Math commands
math:abs
math:acos
math:asin
math:atan
math:ceil
math:clamp
math:clamp number=$(one_of $float $integer) min=$(one_of $float $integer) max=$(one_of $float $integer)
Number restricted to the inclusive range [min, max].
This command accepts the following arguments:
numberthe number to clamp.minthe lower bound of the allowed range.maxthe upper bound of the allowed range.
Examples
math:clamp 15 min=0 max=10
math:cos
math:exp
math:exp number=$(one_of $float $integer)
e (Euler's number) raised to the power of number.
Output
float
The same result is available as math:pow math:e number, but exp doesn't
require knowing about the e constant, and its dedicated implementation is generally
more numerically precise than going through a general-purpose pow.
This command accepts the following arguments:
numberthe exponent to raise e to.
Examples
# Returns 1, since e^0 is 1
math:exp 0
math:floor
math:floor number=$(one_of $float $integer)
The largest integer smaller than number.
Output
float
This command accepts the following arguments:
numberthe number to round down to the nearest integer.
math:ln
math:log
math:pow
math:round
math:round number=$(one_of $float $integer)
Number rounded to the nearest whole number.
Output
float
This command accepts the following arguments:
numberthe number to round to the nearest whole number.
math:sign
math:sin
math:sqrt
math:tan
random
global:random
Random number generation
random:float
random:float to=$(one_of $float $integer)
generate a random floating point number between 0 (inclusive) and 1 (exclusive)
Output
float
This command accepts the following arguments:
to(default:1.0) upper bound (exclusive).
random:float_stream
random:float_stream to=$(one_of $float $integer)
generate a stream of random floating point numbers between 0 (inclusive) and 1 (exclusive)
Output
table_input_stream value=$float
This command accepts the following arguments:
to(default:1.0) upper bound (exclusive).
Examples
# Generate 20 floating point numbers between 0 and 100
random.float_stream 100 | head 20
random:integer
random:integer [to=integer]
generate a random integer between 0 and 1 (or some other specified number)
Output
integer
This command accepts the following arguments:
to(default:2) upper bound (exclusive).
random:integer_stream
random:integer_stream [to=integer]
generate a stream of random integer numbers between 0 (inclusive) and 2 (exclusive)
Output
table_input_stream value=$integer
This command accepts the following arguments:
to(default:2) upper bound (exclusive).
Examples
# Generate 20 integers between 0 and 100
random.integer_stream 100 | head 20
remote
global:remote
Remote code execution
Commands for running code on other machines over SSH: remote:exec runs a closure on one host, remote:pexec runs it across several in parallel, and remote:identity lists the identities your ssh-agent has loaded. remote:host tracks known-hosts entries, the same trust store ssh itself uses.
remote:exec
remote:exec command=command host=string [username=string] [password=string] [host_file=one_of $string $file $glob $re] [--ignore_host_file] [--allow_not_found]
Execute a command on a remote host
Serializes command (a closure), sends it over SSH to host, runs it there in a
fresh crush process, and returns its result. The remote host's key is checked
against host_file unless ignore_host_file is set. Security note: setting
ignore_host_file disables that check entirely (no protection against a
different host answering at that address); allow_not_found instead trusts an
unrecognized host's key on first use and saves it, rather than erroring -- both
weaken protection against a machine-in-the-middle impersonating the remote host.
This command accepts the following arguments:
commandthe command to execute.hosthost to execute the command on.usernameusername on remote machines.passwordpassword on remote machines. If no password is provided, agent authentication will be used.host_file(~/.ssh/known_hosts) known hosts file.ignore_host_file(default:false) skip checking the know hosts file.allow_not_found(default:false) allow missing hosts in the known hosts file. Missing hosts will be automatically added to the file.
Examples
remote:exec {host:name} "my-server.example.com" username="alice"
remote:identity
remote:identity
List all known ssh-agent identities
Output
table_input_stream identity=$string public_key=$binary
remote:pexec
remote:pexec command=command [host=string...] [parallel=integer] [username=string] [password=string] [host_file=one_of $string $file $glob $re] [--ignore_host_file] [--allow_not_found]
Execute a command on a set of hosts
Output
table_input_stream host=$string result=$any
Like exec, but runs command on every host listed in host (up to parallel
of them at a time). pexec always attempts every host in the list, regardless of
whether earlier hosts failed to connect or authenticate -- it never fails outright
just because some, or even all, of the hosts couldn't be reached.
A host that succeeds contributes one row (host/result columns) to the output;
a host that fails contributes no row at all. Instead, the failure is logged as a
warning (see crush:warn:list) naming the host and the underlying error. pexec's
own exit status stays 0 either way, so the only way to tell whether every host
succeeded is to compare the length of the output to the length of the host list
you passed in -- fewer output rows than hosts means some connections failed.
The same host-key verification applies independently to each host -- see exec
for what ignore_host_file/allow_not_found mean for security.
This command accepts the following arguments:
commandthe command to execute.hosthosts to execute the command on.parallel(default:32) maximum number of hosts to run on in parallel.usernameusername on remote machines.passwordpassword on remote machines. If no password is provided, agent authentication will be used.host_file(~/.ssh/known_hosts) known hosts file.ignore_host_file(default:false) skip checking the know hosts file.allow_not_found(default:false) allow missing hosts in the known hosts file. Missing hosts will be automatically added to the file.
Examples
remote:pexec {host:name} "web1.example.com" "web2.example.com" username="alice"
remote:host
global:remote:host
Known remote hosts
remote:host:list
remote:host:list [host_file=one_of $string $file $glob $re]
List all known hosts
Output
table_input_stream host=$string public_key=$string
If a given host key has no hostname, the hostname will be the empty string
This command accepts the following arguments:
host_file(~/.ssh/known_hosts) known hosts file.
remote:host:remove
remote:host:remove [host_file=one_of $string $file $glob $re] @ $(one_of $string $glob $re) @ $(one_of $string $glob $re)
Remove hosts from known_hosts file
Output
integer
Remove all hosts that match both the host and the key filters. Returns the number of host entries deleted.
This command accepts the following arguments:
host_file(~/.ssh/known_hosts) known hosts file.hosthost filter.keykey filter.
sockets
global:sockets
List opened sockets
Lists the TCP and UDP sockets currently open on this machine -- the same information tools like netstat or ss report. Read-only: this namespace can tell you what's listening or connected, but (unlike grpc:connect or io:http) has no way to open a connection of its own.
sockets:tcp
sockets:tcp
List open TCP sockets
Output
table_input_stream local_address=$string local_port=$integer remote_address=$string remote_port=$integer pids=$(list $integer) state=$string
sockets:udp
sockets:udp
List open UDP sockets
Output
table_input_stream local_address=$string local_port=$integer pids=$(list $integer)
stream
global:stream
Stream handling commands
Crush's pipes carry typed streams of rows, not bytes -- stream is where the SQL-like operations on those streams live: filtering (where), sorting, grouping, aggregating, joining two streams, deduplicating, and more. This namespace is imported into the global scope, so every command here works equally well as stream:sort or the bare word sort -- most Crush pipelines are built by chaining these together with |.
stream:all_match
stream:all_match condition=command
True if condition is true for every row of input.
Output
bool
Stops reading input as soon as one non-matching row is found, rather than
always consuming the whole stream. True for an empty input, same as an empty
and chain would be. The columns of the row are exported to condition by
name, exactly like where.
This command accepts the following arguments:
conditionthe condition to check for each row.
Examples
# Are all processes owned by root?
host:procs | all_match {($user == "root")}
stream:any_match
stream:any_match condition=command
True if condition is true for at least one row of input.
Output
bool
Stops reading input as soon as one matching row is found, rather than always
consuming the whole stream. The columns of the row are exported to condition
by name, exactly like where.
This command accepts the following arguments:
conditionthe condition to check for each row.
Examples
# Is there any process using more than 50% of a CPU core?
host:procs | any_match {($cpu > 50)}
stream:avg
stream:avg [field=string]
Calculate the average for the specific column across all rows.
If the input only has one column, the column name is optional. The column type must be numeric or a duration.
This command accepts the following arguments:
fieldThe name of the column to find the average of
Examples
host:procs | avg cpu
stream:concat
stream:concat [field=string] [separator=string]
Concatenate all values of the specified column across all rows
If the input only has one column, the column name is optional. The column can be numeric, or textual.
This command accepts the following arguments:
fieldThe name of the column to concatenateseparator(default:", ") The separator to insert between each element
Examples
host:procs | concat name ":"
stream:count
stream:count
Count the number of rows in the input.
Output
integer
The input type can be any type that can be streamed, such as a table, a list, etc.
If the input type is not a materialized type, such as a $table_input_stream, the whole stream will be consumed by this operation.
Materialized types, i.e. $table, $list and $dict, have a know size, and count will not need to iterate over them to find it.
Examples
# Returns the number of processes on the system
host:procs | count
stream:drop
stream:drop [drop=string...]
Drop specified columns from input stream, copy content of remaining columns into output
This command is does the opposite of the select command. It copies all columns except the ones specified from input to output.
This command accepts the following arguments:
dropthe columns to remove from the stream.
Examples
# Drop memory usage columns from output of ps
host:procs | drop vms rss
stream:each
stream:each body=command
Runs a command one for each row of input
Output
empty
The columns of the row are exported to the environment using the column names.
This command accepts the following arguments:
bodythe command to run.
Examples
host:procs | where {$status != "Sleeping"} | each {echo ("{} is sleepy":format $name)}
stream:fold
stream:fold initial=any body=command
Accumulate a single result across all rows of input using a user-supplied closure.
body is called once per input row, with the accumulator available as acc
and the row's own columns exported by name, exactly like where/each. Its
return value becomes the accumulator for the next row; once the input is
exhausted, the final accumulator is fold's own output. This is the general
escape hatch for one-off aggregations that don't have (or don't need) their own
dedicated command like sum or max.
This command accepts the following arguments:
initialthe accumulator's value before the first row is processed.bodycalled once per row with the accumulator (acc) and the row's own columns as named arguments; its return value is the next accumulator.
Examples
# Sum 1 through 5 by hand
seq 1 6 | fold {($acc + $value)} initial=0
# Build a comma separated string from a column
files | fold {("{}, {}":format($acc, $file))} initial=""
stream:group
stream:group [group_by=string...] [<any>=command...]
Group stream by the specified column(s)
This command accepts the following arguments:
group_bythe column(s) to group by and copy into the output stream.<any>=$commandcreate additional columns by aggregating the grouped rows using the supplied aggregation command. The supplied command will be called once for each group, with a table_input_stream containing all rows within that group. Whatever the command outputs will be the value for the specified column for that group.
Examples
# Group files in current tree by the number of hardlinks pointing to them, show
# the number of files and the sum total file size for each link count. Sort results
# by size.
files --recurse | group links file_count=$count size={sum size} | sort size
stream:head
stream:head [rows=integer]
Return the first row(s) of the input.
Output
A stream with the same columns as the input
This command accepts the following arguments:
rows(default:10) the number of rows to return.
stream:join
stream:max
stream:max [field=string]
Calculate the maximum for the specific column across all rows.
If the input only has one column, the column name is optional. The column can be numeric, temporal, a string or a file.
This command accepts the following arguments:
fieldThe name of the column to find the maximum of
Examples
host:procs | max cpu
stream:median
stream:median [field=string]
Calculate the median for the specific column across all rows.
If the input only has one column, the column name is optional.
The column type must be numeric or a duration.
If the column contains a NaN float value, median fails with an error rather
than silently including it in (or excluding it from) the calculation.
This command accepts the following arguments:
fieldThe name of the column to find the median of
Examples
host:procs | median cpu
stream:min
stream:min [field=string]
Calculate the minimum for the specific column across all rows.
If the input only has one column, the column name is optional. The column can be numeric, temporal, a string or a file.
This command accepts the following arguments:
fieldThe name of the column to find the minimum of
Examples
host:procs | min cpu
stream:prod
stream:prod [field=string]
Calculate the product of the specified column across all rows.
Specifying the column is optional if the stream only has one column. The column type must be numeric.
This command accepts the following arguments:
fieldThe name of the column to find the product of
Examples
seq 5 10 | prod
stream:rename
stream:rename [<any>=string...]
Rename one or more columns of a stream.
Output
A stream with the same columns as the input
Every argument name is the current name of a column, and its value is the new name to give it. Columns not mentioned pass through unchanged.
This command accepts the following arguments:
<any>=$stringmapping from current column name to new column name.
Examples
files | rename file=path
stream:reverse
stream:reverse
Reverses the order of the rows in the input
Output
A stream with the same columns as the input
stream:sample
stream:sample [rows=integer]
Reservoir-sample rows rows from the input.
Output
A stream with the same columns as the input
Every row of input has an equal probability of ending up in the output, and the
whole stream never has to be materialized to pick them -- only rows rows are
ever held in memory at once. Output order is not the input order.
This command accepts the following arguments:
rows(default:10) the number of rows to sample.
Examples
# Pick 5 pseudo-random lines out of a huge file, without reading it all into memory
lines:from big_log_file.txt | sample 5
stream:select
stream:select [copy_fields:string...] [*] [new_field=command]
Pass on some old fields and calculate new ones for each line of input
Examples
# Show only the filename and discard all other columns
files | select file
# Add an extra column to the output of files that shows the time passed since last modification
files | select * age={(time.now() - modified)}
stream:seq
stream:seq [args=integer...] [from=integer] [to=integer] [step=integer]
Return a stream of sequential numbers
With no arguments, seq counts forever starting at 0. Given one to three
unnamed numbers, they're interpreted the same way Python's range does:
seq to counts from 0 up to (but not including) to; seq from to starts
at from instead; seq from to step also sets the step size. The from,
to, and step named arguments below are equivalent to the two- and
three-number unnamed forms, spelled out -- but can't be mixed with the
unnamed form in the same call, since e.g. seq 3 to=10 would leave it
ambiguous which one actually sets the end of the sequence.
This command accepts the following arguments:
args1 to 3 numbers:to,from to, orfrom to step-- see the command's own long help. Can't be combined with the from/to/step named arguments.fromthe first number in the sequence. Defaults to 0.tothe end of the sequence (exclusive). If not specified, the sequence will continue forever.stepthe step size. Defaults to 1.
Examples
seq 3
# Prepend an index column to the output of the files command
zip $(seq) $(files)
stream:skip
stream:skip [rows=integer]
Skip the specified number of rows from the beginning of the stream and return the remainder.
Output
A stream with the same columns as the input
If the stream has fewer than the specified number of rows, an empty stream will be returned.
This command accepts the following arguments:
rows(default:1) the number of rows to skip.
stream:sort
stream:sort [field=string...] [--reverse] [--case_insensitive]
Sort input stream based on one or more of it's columns
Output
A stream with the same columns as the input
If any sort column contains a NaN float value, sort fails with an error rather
than picking an arbitrary position for it, since NaN has no defined ordering relative to
other floats.
This command accepts the following arguments:
fieldthe columns to sort on. Optional if input only has one column.reverse(default:false) reverse the sort order.case_insensitive(default:false) ignore case when sorting textual columns.
Examples
# Show the contents of the current directory, sorted first on type and then on filename
files | sort type file
stream:sum
stream:sum [field=string]
Calculate the sum for the specific column across all rows.
If the input only has one column, the column name is optional.
The column contents must be exactly one of the types $integer, $float, or $duration.
Normally, sum expects the type of the column to be the type to sum over, but sum can also sum over a column of type any, so long as there is at least one row in the table, and all the rows are actually of the same type.
This command accepts the following arguments:
fieldThe name of the column to find the sum of
Examples
host:procs | sum cpu
stream:tail
stream:tail [rows=integer]
Return the last row(s) of the input.
Output
A stream with the same columns as the input
This command accepts the following arguments:
rows(default:10) the number of rows to return.
stream:tee
stream:tee [branches=command...]
Duplicate the input stream into one or more side pipelines, passing the original stream through unchanged.
Output
A stream with the same columns as the input
Each branches block receives its own independent copy of every row and runs
to completion as its own pipeline, in parallel with the others; its own output
is discarded, so a branch is only useful for its side effects (writing to a
file, counting, etc). tee's own output is the untouched original stream, so
it composes directly into a larger pipeline. If a branch fails, the failure is
reported via crush:warn:list rather than aborting tee or the other branches.
This command accepts the following arguments:
branchesone or more pipelines to send an independent copy of the stream through.
Examples
# Write a snapshot to disk while continuing to filter the live stream
host:procs | tee {json:to snapshot.json} | where {($cpu > 50)}
stream:union
stream:union [streams=any...]
Concatenate two or more streams with identical column types into one.
Every row of the first stream is output, in order, followed by every row of the second stream, and so on. All streams must have identical column types.
This command accepts the following arguments:
streamsthe streams to concatenate.
Examples
union $(seq 0 3) $(seq 10 13)
stream:uniq
stream:uniq [field=string]
Only output the first row whenever multiple rows has the same value for the specified column
Output
A stream with the same columns as the input
If no column is given, the entire rows are compared.
This command does not just remove consecutive repeated column values, any repeated column values over the entire stream are removed.
This command accepts the following arguments:
fieldThe field to compare.
Examples
host:procs | uniq user
stream:where
stream:where condition=command
Filter out rows from input based on condition
Output
A stream with the same columns as the input
The columns of the row are exported to the environment using the column names, i.e. if the table the where command is applied to has columns a and b, then the environment will have variables type and name, the variables $type and $name will be set to the values of the columns in the current row on each execution of the closure.
This command accepts the following arguments:
conditionthe condition to filter on.
Examples
# List all subdirectories to the current working directory
files | where {$type == directory}
stream:zip
stream:zip first=any second=any
Combine two streams of data into one containing one row of each input stream in each row of output.
If the two streams have different numbers of rows, the longer stream will be truncated to the length of the shorter one.
This command accepts the following arguments:
firstthe first stream.secondthe second stream.
Examples
# Prepend an index column to the output of the files command
zip $(seq) $(files)
term
global:term
Constants useful for manipulating the terminal, such as changing text color and text weight.
ANSI escape code constants for styling terminal output -- colors (term:red, term:green, ...), term:bold, term:underline, and term:normal to reset. These are plain string values, not commands -- interpolate them directly into a string, e.g. via :format, most often to build a colorful crush:prompt.
types
global:types
Crush built in types and type related builtins.
Every value type Crush knows about, and the methods you can call on instances of it -- string, integer, list, dict, time, duration, table, re, glob, and the rest, each its own sub-namespace of methods (e.g. "hello":upper, $my_list:push value). Also home to the type system's own cross-cutting machinery: class (defining new types), convert, typeof, like (pattern matching), and materialize. Imported into the global scope, so both types:string and bare string refer to the same type.
types:class
types:class [parent=struct]
Create an empty new class
Output
struct
This command accepts the following arguments:
parentthe parent type to inherit members from (if any).
Examples
# Create a class that represents a point in 2D space
$Point := $(class)
$Point:__short_help__ = "A point in 2D space"
$Point:__signature__ = "class Point"
$Point:__long_help__ = "Uses floating point numbers to represent the x and y coordinates"
$Point:__example__ = "$p := ($Point.new(1.0, 2.0))"
# Constructor takes two arguments, x and y
Point:__init__ = {
|$x:$float $y:$float|
$this:x = $x
$this:y = $y
}
Point:len = {
|
short_help = "Returns the distance from the origin"
|
($math.sqrt($this.x*$this.x + $this.y*$this.y))
}
# Overload the `+` operator to add two points. (Only available in expression mode)
Point:__add__ = {
|
short_help = "Add two points together"
$other : $struct "the other point."
|
($Point.new(x=($this.x+$other.x), y=($this.y+$other.y)))
}
$p := $($Point:new x=1.0 y=2.0)
$p:len
$p2 := ($Point.new(x=-1.0, y=2.0))
$p3 := ($p + $p2)
types:convert
types:convert target_type=type [value=any]
Convert the value to the specified type
Converting a value to the type it already holds always works and returns the original value. Most other conversions take the input value, convert it to a string and then attempt to parse that string as the desired type.
The following short cut conversions exist that do not go via a string representation:
$floatto$integerthe value is truncated to its integer part.$integerto$bool0 is false, all other values are true.
If convert's input is a pipeline, convert converts the value in the
pipeline. Otherwise, convert requires a value to be provided as an
argument, and converts that value instead.
This command accepts the following arguments:
target_typethe type to convert the value to.valuethe value to convert.
Examples
convert $integer 1.8
types:definition
types:definition command=command
Returns the definition of the specified closure as a text string
Output
string
Returns nothing if the command is not a closure
Note that the outputted of the definition builtin is reformatted, including switching code between expression mode and command mode.
This command accepts the following arguments:
commandthe closure to show the definition of.
Examples
# returns { $files --recursive '/'}
$all_the_files := {files --recursive /}
definition $all_the_files
types:like
types:like value=any [pattern=any...]
Check if the specified value matches one or more patterns.
Output
bool
A pattern can be a string (exact match), a glob, a regular expression, a type
(checks value's type), or any other value that implements an __is__
method -- like simply calls it. If multiple patterns are given, they're
checked in order and like returns true as soon as one of them matches.
In expression mode, a single pattern can also be checked via the =~
operator (or !~ for the negation).
This command accepts the following arguments:
valuethe value to test.patternthe pattern(s) to test the value against.
Examples
# Match the string "fooo" against the regex ^(ooo)
like fooo ^(ooo)
# Same, in expression mode
(fooo =~ ^(ooo))
# A value matches if it equals any of several patterns
like fooo ^(ooo) *.txt "fooo"
types:materialize
types:materialize
Recursively convert all streams in io to materialized form
Examples
# Put a table of files in the current directory into the variable $f
$f := $(files | materialize)
# Because we materialized the table stream into a table, counting the elements is not a destructive operation.
$f | count
types:typeof
types:typeof [value=any]
Return the type of the specified value.
Output
type
If typeof's input is a pipeline, typeof returns the type of the value in
the pipeline. Otherwise, typeof requires a value to be provided as an
argument, and returns the type of that value instead.
This command accepts the following arguments:
valuethe value to provide the type of.
Examples
# Returns float
typeof 1.8
types:any
type any
Any type.
This is a wildcard type, matching a value of any other type. It shows up as the declared type of a column or argument that intentionally imposes no type restriction -- it is not a type user code constructs values of directly.
types:binary
type binary
Binary data.
A binary value can be created by converting another value, e.g.
convert $binary "hi", or by reading a binary_stream to completion with
materialize, e.g. bin:from ./Cargo.toml | materialize.
Binary data is immutable once created, and unlike string or file it has no legality
constraint at all -- it's simply an arbitrary sequence of bytes, the type to reach for
when data isn't necessarily text or a path. See help string for how the three
sequence-of-data types (string, file, binary) differ. The most similar type is
binary_stream, its one-shot streaming form.
types:binary:__getitem__
types:binary[index=integer]
Returns the byte at the specified offset.
Output
integer
This command accepts the following arguments:
indexindex
Examples
$(bin:from Cargo.toml)[4]
types:binary:len
types:binary_stream
type binary_stream
A stream of binary data.
A binary_stream is obtained by reading binary data without fully loading it into
memory first, e.g. bin:from ./Cargo.toml, or the body of an HTTP response from
io:http.
Like table_input_stream, it can only be read once. Pipe it through materialize to
get a reusable binary value instead.
types:bool
types:command
type command
A piece fo code that can be called.
The most common way to create a command is a closure literal, e.g. {echo hello},
or with named parameters, {|$x| echo $x}. Builtin commands are themselves command
values and can be captured into a variable the same way, e.g. $e := $echo.
A command value is immutable -- calling it runs its body, but that doesn't change the value itself. Reassigning the variable that holds a command is a separate operation from mutating the command.
types:dict
type dict $empty $empty
A mutable mapping from one set of values to another.
Create a dict with the dict:of command, e.g.
dict:of a=1 b=2, or by collecting key/value columns out of piped table input with
dict:collect.
Dicts are mutable: entries can be inserted, removed, or have their value replaced in
place. The most similar type is struct, which is also a mapping from keys to values,
but with a fixed set of keys chosen when the struct is created rather than a dynamic,
mutable set of keys.
types:duration
type duration
A difference between two points in time.
To create your own duration objects, use the duration:of method, for example
duration:of seconds=10
A duration instance has nanosecond precision. It is represented internally as two 64 bit numbers, one for the number of seconds, and one for the nanosecond remainder.
durations are signed, i.e. they can be used to denote a negative span of time. Durations
are immutable values. The most similar type is time: subtracting one time from
another produces a duration, and a duration can be added to or subtracted from a
time.
types:duration:__add__
duration + (delta:duration | time:time)
Add the specified delta or time to this duration.
types:duration:__div__
types:duration:__mul__
types:duration:__neg__
types:duration:__sub__
types:duration:days
types:duration:days
Returns the number of days in this duration, rounded towards zero.
Output
integer
types:duration:hours
types:duration:hours
Returns the number of hours in this duration, rounded towards zero.
Output
integer
types:duration:milliseconds
types:duration:milliseconds
Returns the number of milliseconds in this duration, rounded towards zero.
Output
integer
types:duration:minutes
types:duration:minutes
Returns the number of minutes in this duration, rounded towards zero.
Output
integer
types:duration:nanoseconds_part
types:duration:of
types:duration:of [nanoseconds=integer] [microseconds=integer] [milliseconds=integer] [seconds=integer] [minutes=integer] [hours=integer] [days=integer]
Create a new duration.
Output
duration
Durations are stored as a time span in number of seconds. Because of leap seconds and daylight saving time, adding for example exactly one day to a time value will not always do what you might think, if a leap second or a daylight savings time changeover happened in the interim.
This command accepts the following arguments:
nanoseconds(default:0) the number of nanoseconds in the duration.microseconds(default:0) the number of microseconds in the duration.milliseconds(default:0) the number of milliseconds in the duration.seconds(default:0) the number of seconds in the duration.minutes(default:0) the number of minutes in the duration.hours(default:0) the number of hours in the duration.days(default:0) the number of days in the duration. This is internally represented as the number of seconds in a standard day.
Examples
duration:of minutes=1
types:duration:seconds
types:duration:seconds
Returns the number of seconds in this duration, rounded towards zero.
Output
integer
types:empty
types:file
type file
Any type of file.
A file value is usually written as a bareword or single-quoted path, e.g.
./Cargo.toml or 'my file.txt' -- crush recognizes these as files rather than plain
strings based on their syntax. You can also convert an existing string explicitly, e.g.
convert $file "./Cargo.toml".
A file value simply names a path; the value itself is immutable, though of course the
file it points at on disk can change, be created, or be removed out from under it via
methods like remove or commands like fs:mkdir. See help string for exactly how
file differs from string and binary, the other two types that represent a sequence
of data rather than a single scalar value; glob is also related, matching a whole set
of paths rather than naming a single one.
types:file:__getitem__
types:file:chmod
types:file:chmod [permissions=string...]
Change permissions of this file.
Output
empty
Permissions are strings of the form [classes...][adjustment][modes..].
A class is one of u, g, o, a, signifying file owner, file group, other users and all users, respectively.
The adjustment must be one of +, -, and =, signifying added permissions, removed permissions and set permissions, respectively.
A mode is one of r w, x, signifying read, write and execute permissions.
This command accepts the following arguments:
permissionsthe set of permissions to add.
Examples
./foo:chmod "a=" "u+r" # First strip all rights for all users, then re-add read rights for the owner
types:file:chown
types:file:chown [user=string] [group=string]
Change owner of this file.
Output
empty
This command accepts the following arguments:
userthe owning user for the file.groupthe owning group for the file.
types:file:exists
types:file:mkdir
types:file:mkdir [--ignore_existing]
Create directory
Output
empty
This command accepts the following arguments:
ignore_existing(default:false) Do not throw and error if this directory already exists.
types:file:name
types:file:parent
types:file:read
types:file:remove
types:file:remove [--recursive] [--verbose]
Delete this file
Output
table_input_stream file=$file deleted=$bool status=$string
Returns a stream of deletion failures.
This command accepts the following arguments:
recursive(default:false) If this file is a directory, recursively delete files and subdirectoriesverbose(default:false) If true, emit status updates for deleted files, not just errors
types:file:touch
types:file:touch [--no_create]
Set the modification and access times of file.
Output
empty
If the file doesn't exist, it is created.
This command accepts the following arguments:
no_create(default:false) Do not create the file if it doesn't exist.
types:file:write
types:file:write
Write a binary_stream to this file. If no stream is given, input pipe must be one.
Output
empty
types:float
type float
A numeric type representing any number with floating point precision.
A float literal is a bare number containing a decimal point, e.g. 5.0 or
-3.25.
A Crush float is a IEEE 754 64-bit (double precision) floating point number. Floats are
immutable values. The most similar type is integer; mixing the two in an arithmetic
expression promotes the result to a float.
types:float:__add__
types:float + term=$(one_of $float $integer) # Only available in expression mode
Add this number and the specified term and return the result
Output
float
This command accepts the following arguments:
termthe number to add.
types:float:__div__
types:float / term=$(one_of $float $integer) # Only available in expression mode
Divide this number by the specified factor
Output
float
This command accepts the following arguments:
termthe number to divide by
types:float:__mul__
types:float * term=$(one_of $float $integer) # Only available in expression mode
multiply this number and the specified factor and return the result
Output
float
This command accepts the following arguments:
termthe number to multiply
types:float:__neg__
types:float:__sub__
types:float - term=$(one_of $float $integer) # Only available in expression mode
Subtract the specified term from this number and return the result
Output
float
This command accepts the following arguments:
termthe number to subtract
types:float:infinity
types:float:is_infinite
types:float:is_nan
types:float:max
types:float:min
types:float:nan
types:glob
type glob
A pattern containing wildcards.
Globs are usually created by writing an unescaped string containing
a wildcard character (* or ?), like files *.toml.
If you want to construct a new glob from a string, use the glob:new command, e.g.
glob:new "*.txt".
Globs are immutable. The most similar types are re, which supports much richer
patterns at the cost of more complex syntax, and string, which globs otherwise
resemble but never match by wildcard -- only a real glob value does.
types:glob:__is__
types:glob:__is_not__
types:glob:files
types:glob:files [directory=file]
Perform file matching of this glob.
Output
list $file
This command accepts the following arguments:
directorythe directory to match in. Use current working directory if unspecified.
types:glob:filter
types:glob:filter [columns=string...]
Filter input stream based on this glob.
Output
A stream with the same columns as the input
Search all textual (string and file) columns for matches of the glob, and output the rows that match.
This command accepts the following arguments:
columnsColumns to filter on. Column must be textual. If no columns are specified, all textual columns are used.
Examples
# Recursively search current directory for all files containing four `a` characters in a row
files --recurse | *aaaa*:filter
types:glob:new
types:glob:new glob=string
Create a glob from a string
Output
glob
This command accepts the following arguments:
globthe string representation of the glob.
types:integer
type integer
A numeric type representing an integer number.
An integer literal is a bare number, e.g. 5 or -3. Underscores may
be used as digit separators to make large numbers easier to read, e.g. 1_000_000.
A Crush integer uses signed 128 bit precision. This means that the highest number that can be represented is 170141183460469231731687303715884105727, and the lowest is -170141183460469231731687303715884105728.
Integers are immutable values. The most similar type is float, used for numbers that
need a fractional part; mixing an integer and a float in an arithmetic expression
promotes the result to a float.
types:integer:__add__
types:integer + term=$(one_of $float $integer) # Only available in expression mode
Add this number and the specified term and return the result
This command accepts the following arguments:
termthe number to add
types:integer:__div__
types:integer / term=$(one_of $float $integer) # Only available in expression mode
Divide this number by the specified factor
Dividing an integer by an integer zero is an error. Dividing by a float zero follows IEEE 754 (producing infinity or NaN), since the result is a float.
This command accepts the following arguments:
termthe number to divide by
types:integer:__mod__
types:integer:__mod__ term=integer
Least positive residue after integer division
Output
integer
A divisor of zero is an error.
This command accepts the following arguments:
termthe number to divide by
types:integer:__mul__
types:integer * term=$(one_of $float $integer) # Only available in expression mode
multiply this number and the specified factor and return the result
This command accepts the following arguments:
termthe number to multiply
types:integer:__neg__
types:integer:__rem__
types:integer:__rem__ term=integer
Remainder after integer division
Output
integer
A divisor of zero is an error.
This command accepts the following arguments:
termthe number to divide by
types:integer:__sub__
types:integer - term=$(one_of $float $integer) # Only available in expression mode
Subtract the specified term from this number and return the result
This command accepts the following arguments:
termthe number to subtract
types:integer:max
types:integer:min
types:list
type list $any
A mutable list of items, usually of the same type.
Create a list with the list:of command, e.g. list:of 1 2 3,
or by collecting a column out of piped table input with list:collect.
Lists are mutable: elements can be appended, removed, or replaced in place. The most
similar type is table, which is also an ordered sequence of items but where each item
is a row of several named, differently-typed columns rather than a single value.
types:one_of
type one_of
One of
A one_of value is constructed with the one_of:of command,
e.g. one_of:of $file $string $regex, and names a set of acceptable types rather than a
single one. It's used the same way an ordinary type is -- most commonly to declare that a
signature parameter accepts any one of several types -- rather than being a type user
code creates values of.
types:one_of:__call__
types:one_of:__call__ [types=type...]
Construct a one_of value type with the specified allowed types
Output
type
This command accepts the following arguments:
typesThe allowed types
Examples
one_of:of $file $string $regex
types:re
type re
A regular expression is an advanced pattern that can be used for matching and replacing text.
Regular expressions are usually created by writing using regexp
literal syntax, e.g. files ^(^...$).
If you want to construct a new glob from a string, use the re:new command, e.g.
re:new "[a-z]*\.txt".
Regular expressions are immutable. The most similar type is glob, which supports only
simple wildcard patterns but with much simpler syntax.
types:re:__is__
types:re:__is_not__
types:re:filter
types:re:filter [columns=string...]
Filter input stream based on this regex.
Output
A stream with the same columns as the input
Search all textual (string and file) columns for matches of the regex, and output the rows that match.
This command accepts the following arguments:
columnsColumns to filter on. Column must be textual. If no columns are specified, all textual columns are used.
Examples
# Recursively search current directory for all files containing four `a` characters in a row
files --recurse | ^(aaaa):filter
types:re:new
types:re:new pattern=string
Compile a string into a new regular expression instance.
Output
re
This command accepts the following arguments:
patternthe new regular expression as a string.
types:re:replace
types:re:replace text=string replacement=string
Replace the first match of the regex in text with the replacement
The replacement string may reference capture groups from the match: $0 for
the whole match, $1, $2, ... for positional groups, or $name for a named group
((?P<name>...)). Use ${1} (or ${name}) instead of $1 when the reference is
immediately followed by a character that would otherwise be read as part of the
group number or name.
This command accepts the following arguments:
textthe text to perform replacement on.replacementthe replacement text; may reference capture groups, see above.
Examples
# Replaces the first run of digits
^([0-9]+):replace "a123b456" "X"
# Swap the two halves of a dash-separated pair, using capture groups
^((.*)-(.*)):replace "123-456" "$2-$1"
types:re:replace_all
types:re:replace_all text=string replacement=string
Replace all matches of the regex in text with the replacement
The replacement string may reference capture groups from each match: $0 for
the whole match, $1, $2, ... for positional groups, or $name for a named group
((?P<name>...)). Use ${1} (or ${name}) instead of $1 when the reference is
immediately followed by a character that would otherwise be read as part of the
group number or name.
This command accepts the following arguments:
textthe text to perform replacement on.replacementthe replacement text; may reference capture groups, see above.
Examples
# Replaces every run of digits
^([0-9]+):replace_all "a123b456c789" "X"
# Swap key and value in every space-separated pair
^(([a-z]+)=([0-9]+)):replace_all "a=1 b=2 c=3" "$2=$1"
types:scope
type scope
A scope in the Crush namespace.
A scope is normally not constructed directly -- crush creates one
implicitly for the root namespace ($global) and for every closure or block invocation.
The scope currently executing can be obtained by calling __current_scope__ on any
existing scope value, e.g. $global:__current_scope__.
Scopes are mutable: declaring a new variable (:=) or assignment (=) modifies the
scope it's declared or resolved in.
types:scope:__all__
types:scope:__current_scope__
types:scope:__getitem__
types:scope[name=string]
Return the specified member in the current scope
This command accepts the following arguments:
namethe name of the member to look up.
types:scope:__local__
types:scope:__name__
types:scope:__name__
The name of this scope, or empty if unnamed.
types:scope:__read_only__
types:scope:__resolve__
types:scope:__resolve__ name=string
Resolve the specified member in the current scope
This method looks at the current scope as well as all it parents to resolve the specified member
This command accepts the following arguments:
namethe name of the member to resolve.
types:scope:__super__
types:scope:__super__
The parent of this scope. The root (global) scope returns itself.
Output
scope
types:scope:__use__
types:string
type string
Textual data, stored as an immutable sequence of unicode code points.
A string literal is written between double quotes, e.g. "hello world". A
string is a sequence of legal unicode characters -- nothing else can be represented, and
every crush string is guaranteed to be valid text.
Strings are immutable -- every method that looks like it modifies a string (upper,
replace, trim, ...) returns a new string rather than changing the receiver.
file and binary are the two other types that hold sequences of data rather than a
single scalar value, and it's worth being precise about how they differ from string
and from each other. A file represents an operating system path: a sequence of bytes
that is a legal file name, a system-dependent notion of legality that usually allows byte
sequences that aren't legal unicode (for example, a Latin-1-encoded name on a
system whose text encoding is UTF-8). A binary is simply a sequence of bytes with no
legality constraint at all -- the type to reach for when the data isn't necessarily text
or a path. Because "legal file name" and "legal unicode text" are overlapping but
different constraints, string and file have to be separate types: some strings can't
be legal file names (most commonly one containing a zero byte -- many operating systems
represent a path internally as a zero-terminated byte sequence, so a zero byte can never
be part of one), and some legal file names can't be represented as a string at all.
For convenience, builtin commands that expect a file argument also accept a string,
which crush converts automatically. That conversion doesn't validate the result up
front, though -- passing a string containing a zero byte is accepted silently, and only
fails once the resulting file value is actually used against the filesystem. This isn't
just an implementation shortcut: neither crush nor the computer it's running on can
actually know what does and doesn't constitute a legal file name ahead of time, because
that's up to whatever filesystem the path eventually resolves into, and that can change
from one path component to the next -- a network mount, for instance, can enforce
completely different naming rules than the local filesystem it's mounted under, and
crush has no general way to know a path crosses into one before it's used. Some
obviously-illegal names could be rejected early (a zero byte, for example, is illegal
everywhere), but the only way to be certain a given name is legal is to actually hand it
to the operating system in a real syscall. Going the other way, a file whose bytes
aren't valid unicode can't be losslessly converted to a string either; rather than
erroring, crush falls back to displaying it as the placeholder text
<invalid filename>.
types:string:__getitem__
types:string[idx=integer]
Extract a one character substring from this string.
Output
string
This command accepts the following arguments:
idxindex
types:string:__is__
types:string:__is_not__
types:string:bytes
types:string:bytes
Returns the length (in number of bytes) of the string, as encoded using UTF-8
Output
integer
Note that there are often different ways to generate identical looking strings of different lengths, as in the example below.
Examples
# Returns 2
"é":bytes
# Returns 3
"é":bytes
types:string:ends_with
types:string:ends_with suffix=string
True if this string ends with the specified suffix
Output
bool
This command accepts the following arguments:
suffixsuffix to check for
types:string:format
types:string:format [<any>=any...] [unnamed=any...]
Format arguments into a string
Output
string
This command accepts the following arguments:
<any>=$anyThe named parameters to format into the pattern stringunnamedThe unnamed parameters to format into the pattern string
Examples
"Hello {name}":format name=$name
types:string:is_alphabetic
types:string:is_alphanumeric
types:string:is_alphanumeric
True if every character of this string is alphabetic or numeric
Output
bool
types:string:is_ascii
types:string:is_ascii
True if every character of this string is part of the ascii character set
Output
bool
types:string:is_control
types:string:is_digit
types:string:is_digit [radix=integer]
True if every character of this string is a digit in the specified radix
Output
bool
"123":is_digit # true
This command accepts the following arguments:
radix(default:10) radix to use
types:string:is_lowercase
types:string:is_uppercase
types:string:is_whitespace
types:string:is_whitespace
True if every character of this string is a whitespace character
Output
bool
types:string:join
types:string:join [elements=any...]
Join all arguments by the specified string
Output
string
This command accepts the following arguments:
elementsthe elements to join.
Examples
# Returns "1, 2, 3, 4"
", ":join 1 2 3 4
types:string:len
types:string:len
Returns the length (in number of unicode characters) of the string.
Output
integer
Note that a unicode character is not always what a human would consider a character, and there are often different ways to generate identical looking strings with different numbers of characters, as in the example below.
Examples
# Returns 1
"é":len
# Returns 2
"é":len
types:string:lower
types:string:lpad
types:string:lpad length=integer [padding=string]
Returns a string truncated or left-padded to be the exact specified length
Output
string
This command accepts the following arguments:
lengththe length to pad to.padding(default:" ") the character to pad with.
Examples
# Returns " Hello"
"Hello":lpad 10
# Returns "He"
"Hello":lpad 2
types:string:repeat
types:string:repeat times=integer
Returns this string repeated times times
Output
string
This command accepts the following arguments:
timesthe number of times to repeat the string.
Examples
"Around the world\n":repeat 8
types:string:rpad
types:string:rpad length=integer [padding=string]
Returns a string truncated or right-padded to be the exact specified length
Output
string
This command accepts the following arguments:
lengththe length to pad to.padding(default:" ") the character to pad with.
Examples
# Returns "Helloooooo"
"Hello":rpad length=10 padding=o
# Returns "He"
"Hello":rpad 2
types:string:split
types:string:split separator=string
Splits a string using the specified separator
Output
list $string
This command accepts the following arguments:
separatorthe separator to split on.
Examples
# Returns ["Hello", "World"]
"Hello World":split " "
types:string:starts_with
types:string:starts_with prefix=string
True if this string starts with the specified prefix
Output
bool
This command accepts the following arguments:
prefixprefix to check for
types:string:substr
types:string:substr [from=integer] [to=integer]
Extract a substring from this string.
Output
string
This command accepts the following arguments:
from(default:0) Starting index (inclusive). If unspecified, from start of string.toending index (exclusive). If unspecified, to end of string.
types:string:trim
types:string:upper
types:struct
type struct
A mapping from name to value.
To create a simple immutable struct, use the struct:of command,
e.g. struct:of x=1 y=2; its fields can be read ($s:x) but not reassigned.
To create a mutable struct that supports inheritance and methods, use the class
command; instances created from a class ($MyClass:new ...) do support field
reassignment ($instance:x = 5) from outside the class as well as from within its own
methods.
The most similar type is dict, which is also a mapping from keys to values, but with
keys chosen at runtime rather than fixed named fields, and no support for methods or
inheritance.
types:struct:join
types:struct:join [structs=struct...]
Combine any number of structs into one containing all of their members
Output
struct
On a name collision between two of the given structs, the later one's member is
renamed by appending _2, _3, and so on (repeating until the generated name is
unique) -- the same renaming join, zip and group already use when combining
columns from more than one source, applied here to struct members instead.
Only each struct's own local members are used, not any inherited from a parent
(e.g. via class) -- the same "data struct" semantics struct:of itself uses.
This command accepts the following arguments:
structsthe structs to combine.
Examples
struct:join (struct:of a=1 b=2) (struct:of b=3 c=4)
types:struct:of
types:struct:of [unnamed=any...] [<any>=any...]
Construct a struct with the specified members
Output
struct
Unnamed arguments will be given the names _1, _2, _3, and so on.
Unlike a struct created via the class command, a struct created via struct:of does not have a parent or a __setattr__ method. The lack of a __setattr__ method means that a "data struct" is immutable, though its members may potentially be modified, depending on their type.
This command accepts the following arguments:
unnamedunnamed values.<any>=$anynamed values.
Examples
struct:of foo=5 bar="baz" false
types:table
type table
A table of rows.
A table is created by piping a table_input_stream through materialize, e.g.
files | materialize.
Unlike a table_input_stream, a table is a fixed snapshot: it can be read more than once,
indexed by row number ($t[0]), and asked for its length ($t:len) -- but it has no
methods for adding, removing, or replacing rows. The most similar type is
table_input_stream, the one-shot, streaming form it's materialized from.
types:table:__call__
types:table_input_stream:__call__ [<any>=type...]
return the table_input_stream type with the specified column signature.
Output
type
You usually do this in order to create a pipe specialized to a specific column signature.
This command accepts the following arguments:
<any>=$typethe columns of the stream.
Examples
$pipe := $($(table_input_stream value=$integer):pipe)
types:table:__getitem__
types:table_input_stream[index=integer]
Returns the specified row of the table stream as a struct.
Output
struct
This command accepts the following arguments:
indexthe row index to return.
Examples
$(files)[4]
types:table_input_stream
type table_input_stream
An input stream of table rows.
A table_input_stream is produced by any streaming command -- for example, the
output of files or seq -- or by reading the read member of a pipe object (see
(table_input_stream ...):pipe, under help pipe).
It can only be traversed once: each row is consumed as it's read, so a second pass over
the same stream sees nothing. If you need to read the same rows more than once, pipe the
stream through materialize to turn it into a reusable table. table_output_stream is
the writable counterpart of the same rows.
types:table_input_stream:__call__
types:table_input_stream:__call__ [<any>=type...]
return the table_input_stream type with the specified column signature.
Output
type
You usually do this in order to create a pipe specialized to a specific column signature.
This command accepts the following arguments:
<any>=$typethe columns of the stream.
Examples
$pipe := $($(table_input_stream value=$integer):pipe)
types:table_input_stream:__getitem__
types:table_input_stream[index=integer]
Returns the specified row of the table stream as a struct.
Output
struct
This command accepts the following arguments:
indexthe row index to return.
Examples
$(files)[4]
types:table_input_stream:pipe
types:table_input_stream:pipe
Returns a pipe consisting of a read end and a write end.
Output
struct
Each row of data in the pipe must have the columns specified by this table_input_stream specialization. A pipe is usually created by specializing table_input_stream e.g. like
$pipe := $($(table_input_stream value=$integer):pipe)
The pipe object has three methods:
pipe:writewrite sink for this pipe. Put this method at the end of a pipeline that produces data for the pipe.pipe:readread source for this pipe. Put this method at the start of a pipeline that consumes data from the pipe.pipe:closecall this method once all readers and writers have been created in order to close the pipe.
A pipe object can have arbitrarily many write jobs producing data into the pipe. Each writer simply pipes rows into the pipe:write method.
A pipe object can have arbitrarily many read jobs consuming data from the pipe. Each reader simply consumes rows from the pipe:read method.
Each row written to the pipe will be consumed by exactly one reader job.
In order for the consumer jobs to finish, all the writer jobs must end and the pipe:close method must be called. Once this has happened and all the rows have been processed, the consumer job(s) will finish.
Note that the pipe:close method does not interrupt currently existing read or write jobs, but it does prevent new read and write jobs from being started.
Always fg every writer job before calling pipe:close (readers don't need this --
only writers). pipe:write reads the pipe's internal state on its own worker thread
whenever it happens to get scheduled, with no synchronization against pipe:close;
calling pipe:close before a writer job has actually had a chance to run can silently
drop that writer's entire contribution.
Examples
# Create a pipe
$pipe := $($(table_input_stream value=$integer):pipe)
# Create a job that writes 100_000 integers to the pipe and put this job in the background
$write_job_handle := $(seq 0 100_000 | pipe:write &)
# Create a second job that reads from the pipe and sums all the integers and put this job in the background
$sum_job_handle := $(pipe:read | sum &)
# Put the writer job in the foreground so it fully finishes before the pipe is closed
fg $write_job_handle
# Close the pipe so that the second job can finish
pipe:close
# Put the sum job in the foreground
fg $sum_job_handle
types:table_output_stream
type table_output_stream
An output stream of table rows.
A table_output_stream is obtained from the output member of a pipe object,
created by calling :pipe on a table_input_stream type, e.g.
$p := $($(table_input_stream value=$integer):pipe); $p:output is then a
table_output_stream that rows can be written to, and $p:read is the matching
table_input_stream those same rows can be read back from.
Rows are written with the write method (see help pipe:write). The most similar type
is table_input_stream, its read-side counterpart.
types:table_output_stream:__call__
types:table_output_stream:__call__ [<any>=type...]
return the table_output_stream type with the specified column signature.
Output
type
This command accepts the following arguments:
<any>=$typethe columns of the stream.
types:table_output_stream:write
types:time
type time
A point in time with nanosecond precision.
To get the current time, use time:now. To parse a time from text, use
time:parse.
All time instances use the local time zone.
A time instance has nanosecond precision. It is represented internally as two 64 bit numbers, one for the number of seconds since the Unix epoc, and one for the nanosecond remainder.
Times are immutable values -- arithmetic methods like adding a duration return a new
time rather than changing the receiver. The most similar type is duration, used to
represent the difference between two times.
types:time:__add__
types:integer + term=duration # Only available in expression mode
Add the specified delta to this time
Output
time
This command accepts the following arguments:
termthe number to add
types:time:__sub__
types:time:format
types:time:format format=string
Format this time using a strftime-style pattern string
Output
string
Date specifiers:
%Yyear with century.%yyear without century, zero padded.%Ccentury, zero padded.%mmonth, zero padded.%babbreviated month name.%habbreviated month name.%Bfull month name.%dday of month, zero padded.%eday of month, space padded.%aweekday as abbreviated name.%Aweekday as full name.%wweekday as a number, where 0 is Sunday and 6 is Saturday.%uweekday as a number, where 1 is Monday and 7 is Sunday.%Uweek number of the year (Sunday as first day of week), zero padded.%Wweek number of the year (Monday as first day of week), zero padded.%Gsame to %Y but uses the year number in ISO 8601 week date.%gsame to %y but uses the year number in ISO 8601 week date.%Vsame to %U but uses the year number in ISO 8601 week date.%jday of the year, zero-padded.%Dmonth-day-year format. Same to %m/%d/%y.%xmonth-day-year format. Same to %m/%d/%y.%Fyear-month-day format (ISO 8601). Same to %Y-%m-%d.%vday-month-year format. Same to %e-%b-%Y. Time specifiers:%Hhour (24-hour clock) as a zero-padded number.%khour (24-hour clock) as a space-padded number.%Ihour (12-hour clock) as a zero-padded number.%lhour (12-hour clock) as a space-padded number.%Plocale’s equivalent of either am or pm.%plocale’s equivalent of either AM or PM.%Mminute as a zero-padded number.%Ssecond as a zero-padded number.%ffractional nanoseconds since last whole seconds, zero-padded.%Rhour-minute format. Same to %H:%M.%Thour-minute-second format. Same to %H:%M:%S.%Xhour-minute-second format. Same to %H:%M:%S.%rhour-minute-second format in 12-hour clocks. Same to %I:%M:%S %p. Time zone specifiers:%zUTC offset in the form +HHMM or -HHMM.%Ztime zone name.%:za colon, followed by UTC offset in the form +HHMM or -HHMM. Special characters:%cctime date & time format. Same to %a %b %e %T %Y sans \n.%+ISO 8601 / RFC 3339 date & time format.%sUNIX timestamp, the number of seconds since 1970-01-01 00:00 UTC.%ta literal tab character.%na literal newline character.%%a literal % character.
This command accepts the following arguments:
formatthe format of the time.
Examples
time:now:format "%s"
types:time:now
types:time:parse
types:time:parse format=string time=string
Parse a time string using a strptime-style pattern string
Output
time
After parsing the date, it will be converted to the local time zone. Date specifiers:
%Yyear with century.%yyear without century, zero padded.%Ccentury, zero padded.%mmonth, zero padded.%babbreviated month name.%habbreviated month name.%Bfull month name.%dday of month, zero padded.%eday of month, space padded.%aweekday as abbreviated name.%Aweekday as full name.%wweekday as a number, where 0 is Sunday and 6 is Saturday.%uweekday as a number, where 1 is Monday and 7 is Sunday.%Uweek number of the year (Sunday as first day of week), zero padded.%Wweek number of the year (Monday as first day of week), zero padded.%Gsame to %Y but uses the year number in ISO 8601 week date.%gsame to %y but uses the year number in ISO 8601 week date.%Vsame to %U but uses the year number in ISO 8601 week date.%jday of the year, zero-padded.%Dmonth-day-year format. Same to %m/%d/%y.%xmonth-day-year format. Same to %m/%d/%y.%Fyear-month-day format (ISO 8601). Same to %Y-%m-%d.%vday-month-year format. Same to %e-%b-%Y. Time specifiers:%Hhour (24-hour clock) as a zero-padded number.%khour (24-hour clock) as a space-padded number.%Ihour (12-hour clock) as a zero-padded number.%lhour (12-hour clock) as a space-padded number.%Plocale’s equivalent of either am or pm.%plocale’s equivalent of either AM or PM.%Mminute as a zero-padded number.%Ssecond as a zero-padded number.%ffractional nanoseconds since last whole seconds, zero-padded.%Rhour-minute format. Same to %H:%M.%Thour-minute-second format. Same to %H:%M:%S.%Xhour-minute-second format. Same to %H:%M:%S.%rhour-minute-second format in 12-hour clocks. Same to %I:%M:%S %p. Time zone specifiers:%zUTC offset in the form +HHMM or -HHMM.%Ztime zone name.%:za colon, followed by UTC offset in the form +HHMM or -HHMM. Special characters:%cctime date & time format. Same to %a %b %e %T %Y sans \n.%+ISO 8601 / RFC 3339 date & time format.%sUNIX timestamp, the number of seconds since 1970-01-01 00:00 UTC.%ta literal tab character.%na literal newline character.%%a literal % character.
This command accepts the following arguments:
formatthe format of the time.timethe time string to parse.
Examples
time:parse format="%s" time="1234567890"
types:type
type type
A type.
A type value names one of crush's own types, e.g. $string or
$integer -- typeof returns a value of this kind. Types are mostly used to declare
what kind of value a signature parameter or table column accepts, e.g. via convert or
a class field declaration, rather than being manipulated directly by everyday scripts.
types:type:__is__
types:type:__is_not__
users
global:users
User commands
Commands for querying user accounts and login sessions on this system: users:me for the current user, users:current for everyone currently logged in (tty, login time, ...), users:list for every account that exists, and users[username] to look one up by name -- the resulting struct has a do method to run a closure as that user, e.g. users[root]:do {rm foo.txt}. This reads local system account data, not any particular authentication or identity provider.
var
global:var
Commands related to variables
Commands for working with variables and scopes directly, as values rather than through $name/:=/= syntax: declaring, setting, unsetting, reading, and destructuring, plus var:use/var:unuse for importing a scope's contents into the current one and var:list/var:local for introspecting what's currently in scope. This namespace is imported into the global scope, so e.g. var:let and bare let are the same command.
var:get
var:get name=string
Returns the current value of a variable
A variable by the specified name must already exist in some visible scope before calling
the get builtin, or an error will result.
The get builtin is not normally called directly, simply prefix the $ sigil with the
name of the variable you want to get.
This command accepts the following arguments:
namethe name of the variable to return the value of.
Examples
# These two lines are equivalent
$x
var:get x
var:let
var:let [<any>=any...]
Declare new variables in the current scope.
No variable can exist in the local scope, or an error will result.
The let builtin is not normally called directly, but via the syntactic sugar of the := operator.
This command accepts the following arguments:
<any>=$anythe variables to declare. The value you supply will be the initial value of the variable.
Examples
# These two lines are equivalent
$x := 2
var:let x=2
var:let_destructure
var:let_destructure [names=string...] value=any
Declare new variables in the current scope by destructuring a list, struct, or dict.
Not normally called directly, but via the syntactic sugar of the := operator applied
to a bracketed list of names, e.g. [$a, $b] := $pair. value's elements -- a
list's elements, or a struct's/dict's values in insertion order -- are declared
positionally into names, in order. The number of elements must exactly match the
number of names, or an error results.
This command accepts the following arguments:
namesthe names of the variables to declare, in order.valuethe list, struct, or dict to destructure.
Examples
# These two lines are equivalent
[$a, $b] := [1, 2]
var:let_destructure a b value=[1, 2]
var:list
var:list
Returns a table containing all variable names currently in scope and their types.
Output
table_input_stream name=$string type=$string
A variable is in scope if it exists in the current scope, any of its parents, or any of the scopes used in any of those scopes.
var:local
var:set
var:set [<any>=any...]
Reassign existing variables
A variable by the specified name must already exist in some visible scope before calling
the set builtin, or an error will result.
The set builtin is not normally called directly, but via the syntactic sugar of the = operator.
This command accepts the following arguments:
<any>=$anythe variables to reassign. The value you supply will be the new value of the variable.
Examples
# These two lines are equivalent
$x = 2
var:set x=2
var:set_destructure
var:set_destructure [names=string...] value=any
Reassign existing variables by destructuring a list, struct, or dict.
Not normally called directly, but via the syntactic sugar of the = operator applied
to a bracketed list of names, e.g. [$a, $b] = $pair. Every name must already exist
in some visible scope, exactly like set. value's elements -- a list's elements,
or a struct's/dict's values in insertion order -- are assigned positionally into
names, in order. The number of elements must exactly match the number of names,
or an error results.
This command accepts the following arguments:
namesthe names of the variables to reassign, in order.valuethe list, struct, or dict to destructure.
Examples
# These two lines are equivalent
[$a, $b] = [1, 2]
var:set_destructure a b value=[1, 2]
var:unset
var:unuse
var:unuse [name=scope...]
Make specified scopes not searched by default during scope resolution.
Output
bool
The unuse builtin will recursively go through all parent scopes and remove all uses of the provided scopes through the entire chain.
This command accepts the following arguments:
namethe scopes to unuse.
Examples
# Stop using the stream scope
var:unuse $stream
# This command will now fail, because stream::select is not in scope
select