macro_rules! cmd {
(@ $cmd:literal $(,)?) => { ... };
(@ $first:literal => $($rest:tt)+) => { ... };
($($first:expr),+ => $($rest:tt)+) => { ... };
($($args:expr),+ $(,)?) => { ... };
() => { ... };
(%flow $flow:expr => @ $next:literal => $($rest:tt)+) => { ... };
(%flow $flow:expr => @ $next:literal $(,)?) => { ... };
(%flow $flow:expr => $($next:expr),+ => $($rest:tt)+) => { ... };
(%flow $flow:expr => $($next:expr),+ $(,)?) => { ... };
(%cmd @ $cmd:literal) => { ... };
(%cmd $prog:expr $(, $arg:expr)* $(,)?) => { ... };
}Available on crate feature
std only.Expand description
⌗ 🖥️ ⬡
Builds a CommandFlow from one or more command invocations.
Grammar (informal):
- The
=>operator constructs a linear flow, connecting each command’s stdout to the stdin of the next. - Each direct command segment consists of:
- The first expression as the program.
- Any remaining expressions as arguments to that program.
- Prefixing a string literal with
@splits it into a program and arguments using shell word syntax. - A single command segment forms a command flow of length 1.
Semantics:
- This macro does not invoke a shell.
- Commands are spawned directly through the OS process API.
- Direct segments pass their expressions unchanged as argv words.
@segments only perform shell-style word splitting and quoting.- No variable expansion, globbing, redirection, command substitution, or shell operators are performed.
The @ syntax requires the shell feature.
§Examples
let arg1 = "-F";
let cmd2 = "grep";
// A single direct command.
cmd!("ls").run();
cmd!("ls", arg1, ".").run();
cmd!("ls", "-F", ".").run();
// A literal split into a program and arguments.
#[cfg(feature = "shell")]
cmd!(@ "ls -F .").run();
// Quoting controls argument boundaries.
#[cfg(feature = "shell")]
cmd!(@ r#"echo "hello world""#).run();
// Shell expansion is not performed.
#[cfg(feature = "shell")]
cmd!(@ r#"echo "$HOME" "*.rs""#).run(); // literal "$HOME" and "*.rs"
// Multiple piped commands: `ps aux | grep lib | wc -l`.
cmd!("ps", "aux" => cmd2, "lib" => "wc", "-l").run();
#[cfg(feature = "shell")]
cmd!(@ "ps aux" => @ "grep lib" => @ "wc -l").run();
// Direct and split segments may be combined.
#[cfg(feature = "shell")]
cmd!("printf", "hello world" => @ r#"grep "hello world""# => "wc", "-l").run();§No implicit splitting
Without @, a string is treated as one argv word:
cmd!("ls -F").run(); // executes a program named `ls -F`
cmd!("ls -F", ".").run(); // executes `ls -F` with `.` as its argumentUse cmd!(@ "ls -F") when shell-word splitting is intended.