Processes

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. undef if 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. -1 means 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 before qx// if ordering with prior print matters.

  • %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 STRING contains no shell metacharacters, Perl bypasses the shell and execs the command directly — same optimisation as system. This is faster and avoids one sh -c level of quoting.

  • Single-quote delimiter: qx'...' suppresses Perl’s double-quote interpolation. The literal $var is 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. qXfooX is a syntax error — the delimiter must not be alphanumeric.

  • Backticks don’t capture STDERR: nothing written to the child’s STDERR ends up in the returned string. Redirect with 2>&1 inside the command if you want it, or run the command through open with a pipe for finer control.

  • STDIN is inherited: the child reads from whatever the Perl process had on STDIN at the time of the call. To feed the child specific input, use open in 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 open and read it incrementally.

  • Function form: qx// can also be spelled readpipe when 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// with print to 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/sh on Unix. Commands that rely on bash-isms need an explicit bash -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 status

  • exec — replace the current process with a command; no capture, no return

  • readpipe — the named-function form of qx//; takes the command as a regular string argument

  • open — 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 every qx// call; decode with >> 8 for exit code and & 127 for terminating signal

  • $/ — controls how list-context qx// splits output into lines