sh
I/O redirection short referenceThe [n] is an optional number, as in ‘3’ (not ‘[3]’), that refers to a file descriptor. [n]> file Redirect standard output (or n) to file. [n]>> file Append standard output (or n) to file. [n]< file Redirect standard input (or n) from file. [n1]<&n2 Duplicate n2 to standard input (or n1). [n]<&- Close standard input (or n). [n1]>&n2 Duplicate n2 to standard output (or n1). [n]>&- Close standard output (or n).
bash has all of these operators and more.
0 | standard input |
1 | standard output |
2 | standard error |
File descriptors 3 through 9 are empty by default, but 5 can cause some trouble. These empty file descriptors may be used to temporarily copy one of the default file descriptors. One use of a copy is to redirect standard output to a file temporarily and then back to the terminal (example).
make 2>&1 | grep Error
or
make 2<&1 | grep Error
Why do both of these work? Look at some more examples.
exec
redirectsdash
and bash
both provide at least two syntaxes for manipulating file descriptors.
one, two, threeinto the file
numbers.txt
echo "one, two, three" 1> numbers.txt
In this inline form of redirection, standard output for the echo
command is redirected into numbers.txt
.
exec 1> numbers.txt echo "one, two, three"
This exec
redirection diverts standard output to numbers.txt
for any command that follows it.
The exec
example hints at the fact that Child processes inherit open file descriptors
(TLDP). To further explore this concept let's try the redirection again, but accidentally
leave out exec
:
1> numbers.txt echo "one, two, three"This just creates an empty
numbers.txt
file and then echoes one, two, three
to the terminal. The problem is that the shell spawns one child process to run the redirection, lets that process end, and then creates a new sibling child process for the echo
. To run multiple commands that all inherit the redirection, we need to put the exec
back where it was.
exec 1> numbers.txt echo "one, two, three"With the
exec
back in place, the shell still spawns a new process and redirects stdout
to numbers.txt
, but now the exec
causes the new process to become the parent process for any subsequent commands. Therefore echo
runs as a child process of the redirection, inherits the open file descriptors,and sends
one, two, three
to numbers.txt
rather than the terminal.
Redirecting output first to a file and then back to the terminal can be done using either inline or exec
redirects:
echo "one, two, three" 1> numbers.txt echo "Numbers written."In the first
echo
process, stdout
is redirected to numbers.txt
, but then that process ends. The process for the second echo
has no redirections, and therefore outputs to the terminal.
exec 9>&1 1> numbers.txt echo "one, two, three" exec 1>&9 9>&- echo "Numbers written."
Extra care must be taken when redirecting with exec
due to exec
's reparenting effects. One way to restore stdout
to the terminal is to save the pointer
to the terminal in an unused file descriptor (fd 9 in this case) before redirecting stdout
. This saved copy is carried through the process (and child processes) until it is copied back to stdout
(fd 1).
This example also demonstrates that multiple redirects can be made using a single exec
.
exec 1> numbers.txt echo "one, two, three" exec 1> "$(tty)" echo "Numbers written."
Another way to re-redirect stdout
to the terminal is to use the filename that represents the terminal (via the tty
command in this case).
stdin
and stdout
All of the examples on this page up to this point have explicitly provided both sides of every redirection. This might lead to some confusion because the shorthand forms of redirection are more common. Consider again the first example:
echo "one, two, three" 1> numbers.txt
A more common way to write this would be…
echo "one, two, three" > numbers.txt
The 1
may be omitted because >
redirects fd 1 by default.
Similarly, the contents of a file could be read as stdin
by writing…
cat 0< numbers.txt
…but the more common form would be…
cat < numbers.txt
…where file descriptor 0
is implicit.
exec
is particularly helpful.sh
redirection is to implement it again using C library calls. Maybe do something like: open a pipe, fork
a child process, duplicate (dup2
) file descriptors as needed and close
unused file descriptors, execute (execv
) a program in the child process, write
bytes through the pipe to the child process from the parent process, and close
any remaining unneeded file descriptors.
Submit a comment or correction
2013 Jan 08 | Comments link and errors to stdout example |
2012 Aug 15 | some rewordings |
2011 Sep 11 | markup corrections |
2011 Apr 28 | link to GNU libc manual. reword the dash man page excerpt. |
2011 Jan 25 | another way to get back to the terminal: the terminal's /dev filename |
2010 Dec 15 | posted |