Question
What does the ampersand indicate in this bash command 1>&2
Quick one, 2>&1
redirects stderr to stdout, but what does the ampersand mean? I know if we had 2 > 1
it would output to a file named 1
, what does the ampersand do?
Question
Quick one, 2>&1
redirects stderr to stdout, but what does the ampersand mean? I know if we had 2 > 1
it would output to a file named 1
, what does the ampersand do?
Solution
2>&1
redirects standard error (file handle 2) to the same file that standard output (file handle 1) is currently going to.
It's also a position-dependent thing so:
prog >x 2>&1 >y
will actually send standard error to x
and standard output to y
as follows:
x
;x
;y
;Solution
The &
in &1
duplicates the file descriptor 1
. The duplicated descriptor actually does not behave like a copy, but like an alias of the old one. Duplicating 1
allows multiple streams to be redirected to 1
without overwriting each other.
Example: (no &
)
$ ls existing-file non-existent-file > tmp 2> tmp
$ cat tmp
existing-file
nt-file: No such file or directory
Note that 1
overwrote what 2
wrote. But not when we use &
:
$ ls existing-file non-existent-file > tmp 2>&1
$ cat tmp
ls: non-existent-file: No such file or directory
existing-file
A file descriptor is a handle to a file (or other input/output resource, such as a pipe or network socket). When 1
and 2
are separately redirected to tmp
(as in the first example), they move their tmp
file pointer independently. That's why the file descriptors overwrote each other.
According to the Linux man page:
[Duplicate file descriptors] refer to the same open file description and thus share file offset and file status flags; for example, if the file offset is modified by using lseek(2) on one of the descriptors, the offset is also changed for the other.
Note that even though &
acts like an alias, 2>&1
means redirect 2
to the stream that 1
in currently pointing to. When 1
is redirected to something else, 2
points to the same file it did independently of 1
.
Observe:
$ ls existing-file non-existent-file > tmp 2>&1 > tmp1
$ cat tmp1
existing-file
$ cat tmp
ls: non-existent-file: No such file or directory