sh
I/O redirection examplesIf the annotated code on this page is confusing, read more about I/O redirection without leaving the site or look elsewhere.
Input redirection can be used to temporarily divert the input stream to another source and then resume reading from the original source.
#!/bin/sh exec 9<&0 exec 0<< EOF one two three four five EOF for I in 1 2; do read LINE echo "number: ${LINE}" done exec 8<&0 exec 0<< EOF a b c EOF while read LINE; do echo "letter: ${LINE}" done exec 0<&8 while read LINE; do echo "number: ${LINE}" done exec 0<&9 exec 8<&- 9<&- echo -n "term: " read TERMINAL echo "${TERMINAL}" |
Copy the TERMINAL input streampointerto file descriptor 9. Redirect standard input to read from ahere-document.Read 2 lines (from the here-document) and echo them. Copy the pointer to the here-document stream to file descriptor 8. Read a different here-document as |
echo "alpha" | redirect-input.sh
number: one number: two letter: a letter: b letter: c number: three number: four number: five term: alpha
Mirroring input redirection, output redirection can temporarily divert the output stream to another target and then resume writing to the original target.
#!/bin/sh NUMBERS="$(tempfile)" exec 9>&1 exec 1> "${NUMBERS}" for WORD in "one" "two"; do echo "number: ${WORD}" done LETTERS="$(tempfile)" exec 8>&1 exec 1> "${LETTERS}" for WORD in "a" "b" "c"; do echo "letter: ${WORD}" done exec 1>&8 for WORD in "three" "four" "five"; do echo "number: ${WORD}" done exec 1>&9 exec 8>&- 9>&- echo "--NUMBERS--" cat "${NUMBERS}" echo "--LETTERS--" cat "${LETTERS}" rm "${NUMBERS}" "${LETTERS}" |
Create a temporary file to use as an output destination. Copy the TERMINAL output streampointerto file descriptor 9. Redirect standard output to write to the NUMBERS temporary file. Echooneandtwointo the file. Create a second output file. Copy the NUMBERS stream pointer to file descriptor 8. Redirect standard output to write to the LETTERS temporary file. Echoa,b,andcinto the LETTERS file. Copy the NUMBERS output stream pointer back to |
--NUMBERS-- number: one number: two number: three number: four number: five --LETTERS-- letter: a letter: b letter: c
#!/bin/sh exec 0<< EOF one two three four five EOF exec 9<&0 for I in 1 2; do read LINE echo "number: ${LINE}" done exec 0<&9 9<&- for I in 1 2; do read LINE echo "number: ${LINE}" done |
This does notresetthe stream; |
number: one number: two number: three number: four
Figure 10.3 from the TLDP Linux Kernel Chapter on Networks might help clarify the behavior of file descriptors.
Copying back and forth, to and from file descriptor 9 is pointless in this example, so both of the following lines may be deleted:
exec 9<&0
exec 0<&9 9<&-
Copies of file descriptors are insufficient for reading a stream twice. Instead, temporary files may be used.
#!/bin/sh exec 0<< EOF one two three four five EOF TEMPFILE="$(tempfile)" exec 9>&1 exec 1> "${TEMPFILE}" cat exec 1>&9 9>&- exec 0< "${TEMPFILE}" for I in 1 2; do read LINE echo "number: ${LINE}" done exec 0< "${TEMPFILE}" for I in 1 2; do read LINE echo "number: ${LINE}" done rm "${TEMPFILE}" |
Redirect standard input to read from a here-document. Create a temporary file. Copy the TERMINAL file descriptor to fd 9. Redirect |
number: one number: two number: one number: two
The redirection into the temporary file…
exec 9>&1 exec 1> "${TEMPFILE}" cat exec 1>&9
is verbose. Using an inline redirect is more compact and more idiomatic:
cat > "${TEMPFILE}"
That said, inline redirects can always be rewritten using exec
, but exec
redirects cannot always be rewritten inline.
Submit a comment or correction
2013 Jan 08 | Comments link |
2011 Jan 22 | link to TLDP diagram about file descriptors |
2010 Dec 15 | posted |