From this perldoc page,
To capture a command's STDERR and STDOUT together:
$output = `cmd 2>&1`;
To capture a command's STDOUT but discard its STDERR:
$output = `cmd 2>/dev/null`;
To capture a command's STDERR but discard its STDOUT (ordering is important here):
$output = `cmd 2>&1 1>/dev/null`;
To exchange a command's STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out the old STDERR:
$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
I do not understand how 3 and 4 work, and I am not too sure what I understand about 1 and 2 is right. Below is what I understand. Please correct me where I am wrong.
I know that 0
, 1
and 2
symbolize STDIN
, STDOUT
and STDERR
.
redirect 2 to 1, so that both of them use the same stream now (&
escaped 1
making sure that STDERR
does not get redirected to a file named 1
instead)
redirect 2 (STDERR) to null stream, so that it gets discarded
I do not understand this one. Shouldn't it be just
$output = `cmd 1>/dev/null`;
Also, if the aim is to get the STDERR
messages at STDOUT
, won't 1>/dev/null
redirect everything to /dev/null
?
What is happening here? What is stream 3
? Is it like a temporary variable?
Really, none of this is Perl -- all of this is handled by the shell that you're invoking by using the backticks operator. So your best reading is man sh
, or the Shell chapter of the Unix standard.
In short, though, for #4:
3>&1
: Open FD 3 to point to where stdout currently points.1>&2
: Reopen stdout to point to where stderr currently points.2>&3
: Reopen stderr to point to where FD 3 currently points, which is where stdout pointed before the previous step was completed. Now stdout and stderr have been succesfully swapped.3>&-
: Close FD 3 because it's not needed anymore.