qx//#
Run a shell command and capture its standard output.
qx// (and its twin, the backtick form `STRING`) interpolates
STRING like a double-quoted string, hands the result to the system
shell, waits for the child to finish, and returns whatever the child
wrote to STDOUT. Standard error is untouched — it still goes to the
parent’s STDERR unless you redirect it inside the command. The
child’s exit status lands in $?.
Synopsis#
my $out = `date`;
my $out = qx/date/;
my @lines = `ls -1 /etc`;
my $raw = qx'echo $HOME'; # single-quote form: no Perl interpolation
What you get back#
Context-sensitive:
Scalar context — one string containing the entire captured
STDOUT, including any embedded newlines.undefif the shell or command could not be started.List context — a list of lines, split on the current value of
$/(the input record separator, newline by default). Empty list if the shell or command could not be started.
The exit status of the child is always placed in $?, whether or
not the captured output is used. A child that writes nothing and
exits cleanly yields "" in scalar context, () in list context,
and 0 in $? — distinguishing “started but produced no output”
from “failed to start” requires checking $? against -1 or
$!.
Global state it touches#
$?— set to the child’s wait status (waitpid-style) on every call.-1means the child could not be started, in which case$!holds the reason.$!— set when the shell or command failed to start.$/— governs how list-context output is split into lines.$|— affects whether buffered Perl output reaches the child’s environment before the child runs; set it on output handles beforeqx//if ordering with priorprintmatters.%ENV— exported to the child as its environment.The current working directory, umask, and open file descriptors are inherited by the child.
Examples#
Capture a single line:
my $today = `date`;
chomp $today;
print "today is $today\n";
Capture line-by-line in list context:
my @users = `who`;
for my $line (@users) {
my ($name) = split /\s+/, $line;
print "logged in: $name\n";
}
Interpolation happens before the shell sees the string — Perl variables expand first, shell variables expand in the child:
my $dir = "/etc";
my $out = `ls $dir`; # Perl interpolates $dir
my $sh = qx'echo $HOME'; # single-quote form: $HOME is shell's
Redirect STDERR into the captured stream:
my $both = `gcc -v hello.c 2>&1`;
Discard STDERR, keep only STDOUT:
my $out = `find / -name core 2>/dev/null`;
Check the exit status:
my $out = `make test`;
if ($? == -1) {
die "failed to execute make: $!";
}
elsif ($? & 127) {
die sprintf "make died with signal %d", $? & 127;
}
elsif ($? >> 8) {
die sprintf "make exited with status %d", $? >> 8;
}
Edge cases#
No shell metacharacters: if
STRINGcontains no shell metacharacters, Perl bypasses the shell andexecs the command directly — same optimisation assystem. This is faster and avoids onesh -clevel of quoting.Single-quote delimiter:
qx'...'suppresses Perl’s double-quote interpolation. The literal$varis passed to the shell, which does its own expansion. Useful when the variable names belong to the shell, not to your Perl program.Alternate delimiters:
qx//accepts any balanced or non-alphanumeric delimiter —qx{ls -l},qx(ls -l),qx[ls -l],qx!ls -l!. Pick one that doesn’t collide with shell syntax in your command.qXfooXis a syntax error — the delimiter must not be alphanumeric.Backticks don’t capture STDERR: nothing written to the child’s
STDERRends up in the returned string. Redirect with2>&1inside the command if you want it, or run the command throughopenwith a pipe for finer control.STDIN is inherited: the child reads from whatever the Perl process had on
STDINat the time of the call. To feed the child specific input, useopenin pipe mode instead.Exit status vs
$!: a non-zero$?means the child ran and exited with an error;$!is only meaningful when$?is-1(the shell itself could not be launched).Memory cost in scalar context: the whole captured output is buffered in memory before being returned. For commands that produce very large or unbounded output, open a pipe with
openand read it incrementally.Function form:
qx//can also be spelledreadpipewhen you want a function-call syntax — useful when the command string is built dynamically and you’d rather pass it as a scalar than splice it into a quote-like.Output buffering: Perl flushes its buffered output handles before forking the child, but portability varies. When preceding
qx//withprintto a pipe or file, set$|on that handle to be sure your output reaches the destination before the child starts.Shell selection: the shell used is
/bin/shon Unix. Commands that rely on bash-isms need an explicitbash -c '...'wrapper.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
system— run a shell command without capturing output; reach for this when you only care about the exit statusexec— replace the current process with a command; no capture, no returnreadpipe— the named-function form ofqx//; takes the command as a regular string argumentopen— pipe-mode (open my $fh, "-|", CMD) for streaming a child’s output line by line instead of buffering the whole capture$?— the child wait status set by everyqx//call; decode with>> 8for exit code and& 127for terminating signal$/— controls how list-contextqx//splits output into lines