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
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
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
;From info bash
:
3.6.7 Duplicating File Descriptors
----------------------------------
The redirection operator
[N]<&WORD
is used to duplicate input file descriptors. If WORD expands to one
or more digits, the file descriptor denoted by N is made to be a copy
of that file descriptor. If the digits in WORD do not specify a file
descriptor open for input, a redirection error occurs. If WORD
evaluates to `-', file descriptor N is closed. If N is not specified,
the standard input (file descriptor 0) is used.
The operator
[N]>&WORD
is used similarly to duplicate output file descriptors. If N is not
specified, the standard output (file descriptor 1) is used. If the
digits in WORD do not specify a file descriptor open for output, a
redirection error occurs. As a special case, if N is omitted, and WORD
does not expand to one or more digits, the standard output and standard
error are redirected as described previously.
So 2>&1
duplicates fd 1 onto fd 2.
It copies file descriptor 1 to file descriptor 2. FD2 is stderr and FD1 is stdout, so it makes any output to stderr go to stdout instead.
The ampersand doesn't do anything - it's the character in the 2>&1
operator rather than being a thing in its own right.
bash supports several redirection operators, the 2>&1
operator or the &>
operator tie together the streams of the process before or after redirection.
The ampersand belongs to the "1", so the snippet really has three parts: "2", ">", "&1". They mean, respectively, "take the data from output stream 2 (which is standard error)", "redirect it", and the redirection target, which is output stream 1. So "&" here allows you to redirect to an existing stream, rather than to a file.