1

This question already has an answer here:

What does $ command 1>&2 do? As I understand it this runs the command but with the STDOUT redirected to the STDERR. But I'm not sure exactly how >& works.

I have seen it as $ command 1>&2 and $ command 2>&1.

I think the 1 and 2 are the file descriptors for STDOUT and STDERR, respectively, but I'm not really even sure what that means either.

I have found on SO and other resources that >& is some sort of redirection "thing (operator??)", I'm not sure exactly how it works. Is it a binary operator? Is it even an operator?

Can someone please explain in novice terms what this does.

marked as duplicate by cuonglm, Christopher, don_crissti, Michael Mrozek Jun 5 '15 at 18:22

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3

In that syntax, you are correct that 1 is STDOUT and 2 is STDERR. What it does is "take thing A and send it to wherever thing B is". So, 2>&1, which can also be written 2 > &1, takes STDERR, and sends it to STDOUT. This is not necessarily the original STDOUT. The >& isn't really a unit, it's just often written together that way. The > is the "redirection" operator.

Where it gets interesting is ordering... for example:

$ command 2>&1 > file.out

is different from

$ command > file.out 2>&1

The first sends STDERR to STDOUT, then STDOUT to "file.out", so you get STDERR and STDOUT in the same place. The second sends STDOUT to "file.out", then STDERR to STDOUT, so you end up with STDERR in the terminal window, not in the file.

  • @lcd047 - thanks for catching that. – John Jun 5 '15 at 18:09
  • You got that reversed. You should see these redirections as assignments. The first does 2=&1 and then 1=file.out, so that means STDERR to the console as stdout, and stdout to a file. The second says 1=file.out 2=&1=file.out so that's both to the file. – orion Jun 5 '15 at 18:31
2

& is the prefix you give to file descriptors the shell has open, as opposed to the paths of unopened files (which is the default). STDOUT is almost always file descriptor 1 and STDERR is almost always 2.

For the angle bracket, your shell is usually smart enough to know any number preceding it is going to be the file descriptor. If you omit one it usually assume you're talking about STDOUT for > and STDIN for <.

So putting it together:

# command > /tmp/myFile
# command 1> /tmp/myFile

Both direct command's STDOUT to the flat file called /tmp/myFile

# command >&2
# command 1>&2

Both direct command's STDOUT to the already opened file at file descriptor 2 (STDERR).

# command 2>&1

Redirects anything that would normally be written to STDERR to file descriptor number 1 (STDOUT).

These are generic to any sort of file I/O you do from the shell itself. It's just that the specific file descriptor in question themselves usually have special meaning.

If you wanted you could redirect STDERR to a file you could also tell it to assign file descriptor 2 to a named file:

# command 2> /tmp/newFile 

For example:

[root@edc4 ~]# ./causeError 2>/tmp/containError
[root@edc4 ~]# cat /tmp/containError
Error Message
[root@edc4 ~]#

The Bash HOWTO goes into a lot more detail of how to work with file descriptors in bash. You can open files underneath file descriptors other than the usual three (0, 1, and 2) but that's usually reserved for more elaborate scripts and people generally only deal with the usual three. Even then, it's usually just 1 and 2 people deal with.

0

The numbers are the index values for the pipes. 0 is stdin 1 is stdout and 2 is stderr as you correctly mentioned. You can create more if you want by the way these 3 are the main ones that are created for you to handle inputs and outputs of your process. the chevron > allows you to redirect the stream from data onto a new descriptor.. For example a file ( cmd > ~/somefile.out ) or nothing if you want to suppress it ( cmd > /dev/null) it also allow you to close the pipe ( cmd > &- ) I would careful with that one. but you can also do something like ( cmd 3>&2 2>&1 1>&2 ) to swap standard in and standard out.

The key is to think of it as a wires, like you were a old style dispatcher, and you start with the wire label 0, 1, 2 already plugged in to some default spots, and the > allows you to switch where the wire is connected to.

Not the answer you're looking for? Browse other questions tagged or ask your own question.