bash's output redirection - what's the difference between >> and >&, redirecting and duplicating?
First, anything after >
or >>
is a file name; so > 1
writes to a file named 1
.
Numbers in the other forms given in your example are file descriptors. By default, programs start with file descriptors 0 (standard input), 1 (standard output) and 2 (standard error) connected; when you start a program from an interactive shell, these are connected to the terminal's input and output (you can see these by running ls -l /proc/$$/fd
on Linux).
Specifying a number before >
, >>
or >&
specifies the file descriptor you wish to manipulate; the number has to be right in front of the >
symbol. Thus
echo Example 2> stderr
will print "Example" and create an empty stderr
file (which would contain anything sent to the standard error).
You can think of file descriptors as entries in a table, pointing to files; thus by default:
- 0 points to
/dev/tty
- 1 points to
/dev/tty
- 2 points to
/dev/tty
Specifying 1> file
(or simply > file
) updates file descriptor 1 to point to file
, opened in truncating mode (so its contents are replaced). Specifying 2> 1
updates file descriptor 2 to point to a file named 1
, opened in truncating mode.
Duplicating file descriptors using >&
(or &>
, which is the preferred form) simply updates one file descriptor to point to whatever the other is pointing at. In your last example, > file
updates file descriptor 1:
- 0 points to
/dev/tty
- 1 points to
file
- 2 points to
/dev/tty
and then 2>&1
updates file descriptor 2:
- 0 points to
/dev/tty
- 1 points to
file
- 2 points to
file
(order is significant: > file 2>&1
produces the above, 2>&1 > file
would only end up redirecting file descriptor 1).
The 1>&9
form only works if file descriptor 9 has been opened, e.g. by copying file descriptor 1 to it (9>&1
) or by opening a file (9> file
). This type of construct can be useful to keep track of the original contents of file descriptors when redirecting; thus in a script you could copy 1 and 2 safely away, redirect standard output and error for whatever purpose you need, and then restore them...
The Bash manual has all the details.