In a Unix shell, if I want to combine stderr
and stdout
into the stdout
stream for further manipulation, I can append the following on the end of my command:
2>&1
So, if I want to use head
on the output from g++
, I can do something like this:
g++ lots_of_errors 2>&1 | head
so I can see only the first few errors.
I always have trouble remembering this, and I constantly have to go look it up, and it is mainly because I don't fully understand the syntax of this particular trick.
Can someone break this up and explain character by character what 2>&1
means?
This is just like passing the error to the stdout or the terminal.
That is,
cmd
is not a command:The error is sent to the file like this:
Standard error is sent to the terminal.
2>&1
is a POSIX shell construct. Here is a breakdown, token by token:2
: "Standard error" output file descriptor.>&
: Duplicate an Output File Descriptor operator (a variant of Output Redirection operator>
). Given[x]>&[y]
, the file descriptor denoted byx
is made to be a copy of the output file descriptory
.1
"Standard output" output file descriptor.The expression
2>&1
copies file descriptor1
to location2
, so any output written to2
("standard error") in the execution environment goes to the same file originally described by1
("standard output").Further explanation:
File Descriptor: "A per-process unique, non-negative integer used to identify an open file for the purpose of file access."
Standard output/error: Refer to the following note in the Redirection section of the shell documentation:
Some tricks about redirection
Some syntax particularity about this may have important behaviours. There is some little samples about redirections,
STDERR
,STDOUT
, and arguments ordering.1 - Overwriting or appending?
Symbol
>
mean redirection.>
mean send to as a whole completed file, overwriting target if exist (seenoclobber
bash feature at #3 later).>>
mean send in addition to would append to target if exist.In any case, the file would be created if they not exist.
2 - The shell command line is order dependent!!
For testing this, we need a simple command which will send something on both outputs:
(Expecting you don't have a directory named
/tnt
, of course ;). Well, we have it!!So, let's see:
The last command line dumps
STDERR
to the console, and it seem not to be the expected behaviour... But...If you want to make some post filtering about one output, the other or both:
Notice that the last command line in this paragraph is exactly same as in previous paragraph, where I wrote seem not to be the expected behaviour (so, this could even be an expected behaviour).
Well, there is a little tricks about redirections, for doing different operation on both outputs:
Nota:
&9
descriptor would occur spontaneously because of) 9>&2
.Addendum: nota! With the new version of bash (
>4.0
) there is a new feature and more sexy syntax for doing this kind of things:And finally for such a cascading output formatting:
Addendum: nota! Same new syntax, in both ways:
Where
STDOUT
go through a specific filter,STDERR
to another and finally both outputs merged go through a third command filter.3 - A word about
noclobber
option and>|
syntaxThat's about overwriting:
While
set -o noclobber
instruct bash to not overwrite any existing file, the>|
syntax let you pass through this limitation:The file is overwritten each time, well now:
Pass through with
>|
:Unsetting this option and/or inquiring if already set.
4 - Last trick and more...
For redirecting both output from a given command, we see that a right syntax could be:
for this special case, there is a shortcut syntax:
&>
... or>&
Nota: if
2>&1
exist,1>&2
is a correct syntax too:4b- Now, I will let you think about:
4c- If you're interested in more information
You could read the fine manual by hitting:
in a bash console ;-)
0 for input, 1 for stdout and 2 for stderr.
One Tip:
somecmd >1.txt 2>&1
is correct, whilesomecmd 2>&1 >1.txt
is totally wrong with no effect!File descriptor 1 is the standard output (
stdout
).File descriptor 2 is the standard error (
stderr
).Here is one way to remember this construct (although it is not entirely accurate): at first,
2>1
may look like a good way to redirectstderr
tostdout
. However, it will actually be interpreted as "redirectstderr
to a file named1
".&
indicates that what follows is a file descriptor and not a filename. So the construct becomes:2>&1
.redirects stdout to
afile.txt
. This is the same as doingTo redirect stderr, you do:
>&
is the syntax to redirect a stream to another file descriptor - 0 is stdin, 1 is stdout, and 2 is stderr.You can redirect stdout to stderr by doing:
Or vice versa:
So, in short...
2>
redirects stderr to an (unspecified) file, appending&1
redirects stderr to stdout.