Why redirect output to 2>&1 and 1>&2?
Sometimes you want to redirect both stdout and stderr to the same location, This is when >&
is used – it points one file descriptor to another.
For example, if you want to write both stdout and stderr to the same file (be it /dev/null
or output.txt
), you can redirect them separately, with
app 1>/dev/null 2>/dev/null
or you could redirect one file descriptor to the file, and the other file descriptor into the first one:
app 1>/dev/null 2>&1
app 2>/dev/null 1>&2
In the first example, 2>&1
points file descriptor #2 to where #1 is already pointing. The second example achieves the same, just starting with stderr instead.
As another example, there are cases when stdout (file descriptor #1) is already pointing to the desired location, but you cannot refer to it by name (it may be associated with a pipe, a socket, or such). This often happens when using process expansion (the ` `
or $( )
operators), which normally only captures stdout, but you may want to include stderr in it. In this case, you would also use >&
to point stderr to stdout:
out=$(app 2>&1)
Another common example is a pager, or grep
, or similar utility, since the pipe |
normally only works on stdout, you would redirect stderr to stdout before using the pipe:
app 2>&1 | grep hello
How to know which of 2>&1
or 1>&2
is correct? The already set up file descriptor goes to the right of >&
, and the file descriptor you want to redirect goes to the left. (2>&1
means "point file descriptor #2 to file descriptor #1".)
Some shells have shortcuts for common redirections; here are examples from Bash:
1>
can be shortened to just>
1>foo 2>&1
to>&foo
or&>foo
2>&1 | program
to|& program
One situation when you need it is when you want to display strace
output in a pager. strace
prints its output to standard error and pipes generally connect standard output to standard input, so you have to use the redirect:
strace -p $pid 2>&1 | less
Sometimes you want to redirect both stdout
(1
) and stderr
(2
) to the same location (/dev/null
, for example). One way of achieving this would be:
$ program 1>/dev/null 2>/dev/null
But most people shorten this by redirecting stderr
to stdout
with 2>&1
:
$ program 1>/dev/null 2>&1
An even shorter version is:
$ program >&- 2>&-
2: It is for when you will have output coming from both standard error and standard out, and you want them composed into a single string.
1: When you want to manipulate the output of both standard error and standard out.