sh
I/O redirection, some tricky thingsAs noted in the corresponding example, file descriptors do not keep track of stream position. One consequence is that scripts that need to read some values from stdin
more than once must save the values to a temporary file.
echo "one two three" | ( TEMPFILE="$(tempfile)" cat 1> "${TEMPFILE}" cat "${TEMPFILE}" cat "${TEMPFILE}" rm "${TEMPFILE}" )
one two three one two three
<&
and >&
behave the same way, but using them appropriately improves code clarity.The following two examples behave identically, suggesting that <&
and >&
both just call dup2()
(a quick look at the dash source code supports this idea).
exec 9>&1 1> numbers.txt echo "one, two, three" exec 1>&9 9>&-
Switching the direction of the operators works fine:
exec 9<&1 1> numbers.txt echo "one, two, three" exec 1<&9 9<&-
A mixed up combination of the two redirection operators also behaves identically, but is more confusing to read:
exec 9>&1 1> numbers.txt echo "one, two, three" exec 1<&9 9>&-
Using implicit file descriptors also works:
exec 9>&1 > numbers.txt echo "one, two, three" exec >&9 9>&-
But switching one of the implicit operators will not work:
exec 9>&1 > numbers.txt echo "one, two, three" exec <&9 9>&-
(The last line copies fd 9
to stdin
instead of copying it back to stdout
).
The same is true for input redirections. The following two examples behave identically:
( exec 9<&0 0< numbers.txt cat exec 0<&9 9<&- )
( exec 9>&0 0< numbers.txt cat exec 0>&9 9>&- )
Note: parentheses are used in this example so that the code will run properly if typed or pasted directly into a terminal (see the section Grouping Commands Together
in the dash manpage). They would not be needed within a script.
Submit a comment or correction
2013 Jan 08 | Comments link |
2011 Apr 28 | mention dup2() . change emphasis to <& and >& , rather than < and > . more examples. |
2010 Dec 15 | posted |