Gathering Output from a Program

Problem

You want to run a program and collect its output into a variable.

Solution

Either use backticks:

$output = `program args`;   # collect output into one multiline string
@output = `program args`;   # collect output into array, one line per element

Or use Section 16.4:

open(README, "program args |") or die "Can't run program: $!\n";
while(<README>) {
    $output .= $_;
}
close(README);

Discussion

The backticks are a convenient way to run other programs and gather their output. The backticks do not return until the called program exits. Perl goes to some trouble behind the scenes to collect the output, so it is inefficient to use the backticks and ignore their return value:

`fsck -y /dev/rsd1a`;       # BAD AND SCARY

Both the open function and the backtick operator call the shell to run their commands. This makes them unsafe when used in a program with special privileges.

A high-level workaround is given in Section 19.6. Here’s a low-level workaround, using pipe, fork, and exec:

use POSIX qw(:sys_wait_h);

pipe(README, WRITEME);
if ($pid = fork) {
    # parent
    $SIG{CHLD} = sub { 1 while ( waitpid(-1, WNOHANG)) > 0 };
    close(WRITEME);
} else {
    die "cannot fork: $!" unless defined $pid;
    # child
    open(STDOUT, ">&=WRITEME")      or die "Couldn't redirect STDOUT: $!";
    close(README);
    exec($program, $arg1, $arg2)    or die "Couldn't run $program : $!\n";
}

while (<README>) {
    $string .= $_;
    # or  push(@strings, $_);
}
close(README);
               
               

See Also

The section on “Cooperating with Strangers” ...

Get Perl Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.