in reply to Reading from STDOUT after Redirecting it.

It might be worth pointing out that re-opening STDOUT within your perl script will only affect stuff printed by that perl script and not the output from programs you spawn from within your perl script using system. They have their own set of file handles which are independant of those in your script.

There are three main ways of capturing the output from a spawned command.

  1. my $output = `cmd args`;
  2. my $output = qx/cmd args/;
  3. open IN, "cmd args |" or die $!; while( <IN> ) { # do something with each line of input } close IN;

The latter form can be convenient if your command produces a large volume of output but you only need a few or selected lines.


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


Replies are listed 'Best First'.
Re: Re: Reading from STDOUT after Redirecting it.
by Thelonius (Priest) on Jul 03, 2003 at 04:58 UTC
    It might be worth pointing out that re-opening STDOUT within your perl script will only affect stuff printed by that perl script and not the output from programs you spawn from within your perl script using system. They have their own set of file handles which are independant of those in your script.
    I don't think that's true; the child process should inherit all the file handles.

      Child processes inherit all file descriptors, but a file handle is an internal Perl thing and isn't inherited in the way you'd expect.

      When a new process starts up, standard in is on file descriptor 0, standard out on file descriptor 1, and standard error on file descriptor 2. To redirect one of these, a Perl script has to assign a new file to one of these file descriptors. But that's not what happens by just reassigning STDOUT:

      #!/usr/bin/perl open(STDOUT,"> /tmp/t26.out");
      $ strace -e open perl /tmp/t26
      ...
      open("/tmp/t26.out", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
      
      Fortunately, it's not that hard to work around; open always returns the lowest numbered file descriptor, so closing STDOUT right before re-opening it will do what you expect:
      #!/usr/bin/perl close(STDOUT); open(STDOUT,"> /tmp/t27.out");
      $ strace -e open perl /tmp/t27
      ...
      open("/tmp/t27.out", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 1
      
Re: Re: Reading from STDOUT after Redirecting it.
by ccarden (Monk) on Apr 01, 2004 at 21:29 UTC
    One variation:
    open(CMD, "($cmd | sed 's/^/STDOUT:/') 2>&1 |"); print " test\n" if $DEBUG; while (<CMD>) { if (!s/^STDOUT://) { print " Command failed: ", $_; exit 2; } else { chomp; @argTest = split; } }