0

What does this do? I cannot find any information about what &1 and &2 are in bash.

$ echo "Hello" >&1
Hello

$ echo "Hello" >&2
Hello

$ echo "Hello" >&3
bash: syntax error near unexpected token `&'

I know that you can redirect standard and error output to a file, but what does the ampersand do in these cases?

Xiphias
  • 4,468
  • 4
  • 28
  • 51
  • 1
    Check out the links/answers [from this question](http://stackoverflow.com/questions/4749226/whats-the-diference-of-redirect-an-output-using-and-2). – admdrew Jan 10 '14 at 22:52

3 Answers3

3

>& is a variant on the > pipeline operation. While > redirects output into a named file (or the device's representation in the filesystem, such as /dev/console), >& redirects the output to one of the standard output streams. The most commonly used exaples are stream 1 (stdout) and stream 2 (stderr). Note that these are the same numbers you can use in front of the > or >& operators to say which stream's output you want to redirect.

echo "hello" >&1 is redundant; you're redirecting stdout to stdout. (echo "hello" 1>&1 would mean the same thing, of course.)

A more interesting example: echo "hello" 2>&1 redirects the echo command's error output from stderr to stdout, combining them into a single stream. This one is often useful if you want to run all the output through a single pipe rather than having them treated separately. echo "hello" 2>&1 | tee log, for example, captures a copy of both normal output and error messages into a single log file.

BroSlow points out that, in version 4 and later of the bash shell, |& can be used as a shorthand for combining the streams, equivalent to 2>&1. Good to know. (I still move between shells too frequently to have started using that one.)

keshlam
  • 7,931
  • 2
  • 19
  • 33
  • I would like to (somewhat pedantically) point out that `>` and `>&` are completely different operators (see the [shell grammar](http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html)). `>&2` is not a case of using redirection `>` to redirect to `&2`. This distinction explains why `> file` and `>& 2` (with space) works, while `> &2` fails, and it avoids thinking that `&2` somehow means "stderr". – that other guy Jan 10 '14 at 23:43
  • Valid point; thanks for the clarification. When I'm a bit more awake I'll fix my answer. – keshlam Jan 11 '14 at 00:26
  • I already fixed the syntax errors ^___^ – that other guy Jan 11 '14 at 02:06
  • Also might be useful to some that `2>&1 |` is equivalent to `|&` as of bash 4 – Reinstate Monica Please Jan 11 '14 at 10:06
  • (Note that this is similar to the recent question about what the `=!` operation was in C, where the answer was "you're parsing it wrong, that's two operations". In this case the mistake was looking for documentation on `&2` rather than on `>&`. I've been making the same mistake all these years, of course; thanks to that other guy for pointing it out... but this is a good reminder that if we can't find documentation on something it may be because we've drawn the wrong box around it.) – keshlam Jan 11 '14 at 15:50
1

Bash has several file descriptors used for input and ouptut.

  • 1 is stdout
  • 2 is stderr
  • 3-9 can be used for other i/o (for example if you're using 1 to read from a file in a file loop, you can use 3 to read user input)
  • 10+ is generally used by bash internally, though can be requested from bash if needed

Now for your examples, it's probably easier to view if you split the & from the file descriptor. Both >& and >& are functionally equivalent and redirect from a given file descriptor to another. So in your examples:

The echo command will print whatever you give it to stdout (1), which in this case you redirect to stdout, so the redirection doesn't change anything.

$ echo "Hello" >& 1

The output of the echo command is redirected, and instead of going to stdout goes to stderr.

$ echo "Hello" >& 2

The output of the echo command is redirected, and instead of going to stdout bash tries to send it to file descriptor 3, however it hasn't been allocated yet, so bash throws an error.

$ echo "Hello" >& 3    

You can allocate it to /dev/stdout for example, and then get the same result as your first redirection example.

$ exec 3<> /dev/stdout
$ echo "Hello" >& 3
Hello
Reinstate Monica Please
  • 11,123
  • 3
  • 27
  • 48
0
1 is stdout Standard Out
2 is stderr Standard Error
& indicates that what follows is a file descriptor and not a filename ("fold a file descriptor into another")

common code is redirect stdderr to stdout

2>&1

then

mycommand 2>&1 1>logfile

or

mycommand > afile.txt 2>&1
venergiac
  • 7,469
  • 2
  • 48
  • 70