sh I/O redirection, some tricky things

Reading the full contents of a stream twice

As 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.

Example

echo "one two three" | 
( TEMPFILE="$(tempfile)"
  cat 1> "${TEMPFILE}"
  cat "${TEMPFILE}"
  cat "${TEMPFILE}"
  rm "${TEMPFILE}" )
one two three
one two three

When used with explicit file descriptors, <& and >& behave the same way, but using them appropriately improves code clarity.

Output redirection

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).

Input redirection

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.

Found a mistake?

Submit a comment or correction

Updates

2013 Jan 08 Comments link
2011 Apr 28 mention dup2(). change emphasis to <& and >&, rather than < and >. more examples.
2010 Dec 15 posted