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 |