Best way to capture output from system command to a text file?

40,409

Solution 1

Same as MVS's answer, but modern and safe.

use strict;
use warnings;

open (my $file, '>', 'output.txt') or die "Could not open file: $!";
my $output = `example.exe`; 
die "$!" if $?; 
print $file $output;

easier

use strict;
use warnings;

use autodie;

open (my $file, '>', 'output.txt');
print $file `example.exe`;

if you need both STDOUT and STDERR

use strict;
use warnings;

use autodie;
use Capture::Tiny 'capture_merged';

open (my $file, '>', 'output.txt');
print $file capture_merged { system('example.exe') };

Solution 2

Redirecting the output with plain > will only catch STDOUT. If you also want to catch STDERR, use 2>&1:

perl -e 'system("dir blablubblelel.txt >out.txt 2>&1");' 

For more details, see Perlmonks

Solution 3

When you want recirect output permanently, you can do:

#redirect STDOUT before calling other functions
open STDOUT,'>','outputfile.txt' or die "can't open output";
system('ls;df -h;echo something');  #all will be redirected.
Share:
40,409
int80h
Author by

int80h

Updated on July 05, 2022

Comments

  • int80h
    int80h almost 2 years

    I’m trying to capture output from using Perl’s system function to execute and redirect a system command’s ouptut to a file, but for some reason I’m not getting the whole output.

    I’m using the following method:

    system("example.exe >output.txt");
    

    What’s wrong with this code, or is there an alternative way of doing the same thing?

  • tchrist
    tchrist over 12 years
    I really cannot imagine why you would do all that, not even the first. And you still missed stderr.
  • Joel Berger
    Joel Berger over 12 years
    First of all, this post began as a comment on the outdated practices in MVS's answer. Second I didn't do "all that", just checked what I should. Third if it is "all that" it just shows how nice autodie is. And fourth, how did I miss STDERR? Fifth, yes you can do it all with shell redirection, but Frank already did that, and I don't trust the Windows shell/ I don't have a windows computer to test anything on so lean on solved wheels.
  • Joel Berger
    Joel Berger over 12 years
    @tchrist, Other than shell redirection, how would you do it?
  • MVS
    MVS over 12 years
    Just to clarify, my answer was meant to be a code snippet just like in the question. I didn't include strict or warnings because I assume he already has them. My mistake about or vs. ||, though. Either one works here, but or is better for error checking, so I'll edit that. I was coding in PHP at the time and got my wires crossed a little. As for the rest, TMTOWTDI. :)
  • Joel Berger
    Joel Berger over 12 years
    @MVS, no, its the lexical filehandle, the 3-arg open and checking the status of the backtick execution that I care about. don't care about the or, and I always put in strict and warnings for any newbies present
  • tchrist
    tchrist over 12 years
    Perl knows about 2> stuff even on Micosoft-ridden ports. Ilya put it in. And even he didn’t, we certainly know how to dup our descriptors correctly.
  • tchrist
    tchrist over 12 years
    @Joel I would simply use Perl’s system for what it was designed for, is how I would do it. It’s smarter than you might think, and really, if it isn’t good enough to handle so basic an operation as this one, then there is a Problem that needs fixing. if (system("proggie >outfile 2>&1") != 0) { ... }
  • Joel Berger
    Joel Berger over 12 years
    @tchrist, I do not know the shell commands well. Franks answer already had that so, I'm not sure why my answer is worth your ire. Further it seems that other people have the same concerns/lack-of-shell-knowledge as I have stackoverflow.com/q/7809740/468327 so I think its worth knowing a second way of accomplishing this.
  • Znik
    Znik about 10 years
    this is not answer. this method use asker but wants another.
  • Znik
    Znik about 10 years
    this doesn't redirect output for for commands called by 'system' function. This workaround has big but. When 'example.exe' generate very big output, you can easly overflow available memory.
  • DataGuru
    DataGuru almost 10 years
    Capture::Tiny has now been extended with Capture::Tiny::Extended, you can have ($out, $err, $retval ) = capture { system( "run system command" ) } check out rpm.pbone.net/index.php3/stat/45/idpl/21405428/numer/3/nazwa‌​/… for more information
  • Chad Nouis
    Chad Nouis over 8 years
    This example merely adds quotation marks around output.txt. Quotes aren't necessary for a file name without spaces. Its effect is identical to that of the question.
  • Marki555
    Marki555 over 2 years
    @DataGuru Capture::Tiny::Extended seems to be abandoned since 2011 and most of its features are already in original Capture::Tiny.
  • Marki555
    Marki555 over 2 years
    Capture::Tiny::Extended seems to be abandoned since 2011 and most of its features are already in original Capture::Tiny (last updated in 2018), so better use this one.