44

I have come across several commands that use 2>&1 and 1>&2, but I quite can't get my head around the purpose of using it and when I should be using it.

What I understand

I know that 1 represents standard out and 2 represents standard error. I understand that 2>&1 combines the output of 2 to 1 and vice versa.

What I don't get

  1. When should I be using it?
  2. What purpose does it serve?

7 Answers 7

46

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

5
  • I had no idea that doing app 1>/dev/null 2>&1 would mean that 2>&1 would point to the file that 1 was already redirecting to. I take it I could just as easily do app > /dev/null &>? Jun 14, 2012 at 1:24
  • I am having a hard time understanding the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left. What do you mean by the already set up file descriptor? What does it mean the right of? Jun 14, 2012 at 1:25
  • i.imgur.com/x3fnN.jpg Jun 14, 2012 at 8:38
  • Sorry unless you were intending to teach me directions, I don't follow the statement you made as previously noted. Jun 15, 2012 at 6:35
  • 2
    Take each file descriptor redirect one at a time, from left to right, and apply those rules in that order. If you first direct stdout to a file, then redirect stderr to where stdout us now pointing, then stderr and stdout will go to the same file. If you swapped those two redirects around, then you would get different results (redirect stderr to where stdout is going now, then move stdout to point to another file, while stderr continues where it was pointed at).
    – Jason
    Aug 4, 2014 at 21:14
2

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
2
  • What do you mean by pipes generally connect standard output to standard input? Jun 14, 2012 at 0:57
  • 2
    I mean that pipe (|) take the standard output of the first command and connect it to the standard input of the second command.
    – jpalecek
    Jun 14, 2012 at 1:05
2

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>&-
1

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.

2
  • What do you mean by manipulate? My understanding is that anything redirected to >2 is sent to /dev/null. Or have I completely got it wrong? Jun 14, 2012 at 0:45
  • That is not correct. By manipulate I mean pipe it to grep or something similar. See here for an example.
    – soandos
    Jun 14, 2012 at 0:46
0

I use it to start a detached job:

someProgram 2>&1 >& my.log &

then I can log out, and someProgram will still be running. The functionality is provided by GNU Screen, tmux and some other programs -- but here it is achieved with none of external dependencies.

5
  • 1
    That only works as long as there's no SIGHUP sent to the program. Better use nohup or disown in such cases.
    – slhck
    Jul 27, 2013 at 22:06
  • @slhck: ok. But if I woudn't send SIGHUP to program -- no one will, right?
    – Adobe
    Jul 28, 2013 at 18:42
  • No, the controlling terminal will warn processes of a logout with SIGHUP. In practice, if you run a remote shell through SSH and exit, your process will die as well, for example.
    – slhck
    Jul 28, 2013 at 18:45
  • @slhck: Can't be true: I use it for some couple of years -- I logout of ssh, and the process is still running.
    – Adobe
    Jul 28, 2013 at 19:36
  • I will have to look this up in more detail, but just putting programs into background hasn't worked for me in all cases, and it definitely does not even work on my local machine. Zsh and Bash behave differently here as well, it seems.
    – slhck
    Jul 28, 2013 at 19:54
0

Imagine there is a directory named try that has these three files: file file1 and file2.

Now run this command:

cat file file1 file2 file3

The first three files open but cat throws an error while opening the fourth one as it does not exist.

Now run:

cat file file1 file2 file3 1>outfile 2>&1

You will not see any output on the screen: Firstly 1>outfile will redirect the output of the command to outfile and then it will redirect (2>&1) the error thrown while trying to open file3 to outfile.

1>&2 works similarly and redirects the error stream to standard output.

Hope this helps!

0

The case when re-directing stderr to stdout has already been covered here (e.g. use it to filter (grep) error messages).

The other case is redirecting stdout to stderr. A common usecase (at least for me) is to send warnings/error messages printed with "echo" (in my shellscripts) to the stderr (so they can catch the attention of the user more easily).

For example,

echo "file \"${file\" does not exist..." 1>&2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .