in reply to capturing stderr of a command, invoked via backticks

While probably shell-specific, this works for me:

  my @output = `./script 2>&1 | cat`;

Of course that co-mingles the script's STDOUT and STDERR.

-David

Replies are listed 'Best First'.
Re^2: capturing stderr of a command, invoked via backticks (2>&1)
by tye (Sage) on Sep 08, 2007 at 04:38 UTC

    Trivia:

    The "| cat" part is superfluous. What's more, if you drop it, then you get a little-known feature of Perl to kick in and you have a solution that doesn't require support from the shell. Unfortunately, it isn't implemented in all builds of Perl. So you can avoid the shell when using a Unixy perl but still need the shell to handle "2>&1" for you in other environments (and so this doesn't work on Win98, if you can even find a copy).

    If you give Perl a command that contains no shell meta characters, then Perl just splits the command on whitespace and execs the specified program itself, skipping the shell, as if you'd passed a list of parameters to exec. The little-known feature is that if you give a command that only contains two shell meta characters and those are the > and the & in 2>&1 and that is at the end of the command, then Perl strips that off the end, splits the rest up, does a quick dup2(1,2) (which makes STDERR a dup of STDOUT), and execs the specified program directly.

    This is a feature of exec in Unixy perls. But Unixy perls implement system and qx by using this same exec code so the feature applies in this case as well.

    - tye        

      The "| cat" part is superfluous.
      Hmmm, you're right of course. I think I formed the habit from shell-isms like so:
      ./script 2>&1 > file
      In that case, without the |cat STDERR is not redirected to file, but that's probably another of my mis-understandings of the mechanism involved.

      -David

        foo 2>&1 >file is useful but does something other than WYM (what you mean). Order matters. 2>&1 changes STDERR to go where STDOUT currently is and "redirectives" are processed from left to right. So foo 2>&1 >file | bar sends foo's STDOUT to file and foo's STDERR to bar's STDIN. What you want is foo >file 2>&1 which sends both STDOUT and STDERR to file (you have to dup STDERR to match STDOUT after you've redirected STDOUT to the file).

        - tye