First, note that the syntax for closing is
6<&-, depending on whether the file descriptor is being read for writing or for reading. There seems to be a typo or formatting glitch in that blog post.
Here's the commented script.
exec 5>/tmp/foo # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar # open /tmp/bar for reading, on fd 6
cat <&6 | # call cat, with its standard input connected to
# what is currently fd 6, i.e. /tmp/bar
while read a; do #
echo $a >&5 # write to fd 5, i.e. /tmp/foo
There's no closing here. Because all the inputs and outputs are going to the same place in this simple example, the use of extra file descriptors is not necessary. You could write
cat </tmp/bar |
while read a; do
Using explicit file descriptors becomes useful when you want to write to multiple files in turn. For example consider a script that outputs data to a data output file and logging data to a log file and possibly error messages as well. That means three output channels: one for data, one for logs and one for errors. Since there are only two standard descriptors for output, a third is needed. You can call
exec to open the output files:
echo "first line of data"
echo "this is a log line" >&3
if something_bad_happens; then echo error message >&2; fi
exec &>- # close the data output file
echo "output file closed" >&3
The remark about efficiency comes in when you have a redirection in a loop, like this (assume the file is empty to begin with):
while …; do echo $a >>/tmp/bar; done
At each iteration, the program opens
/tmp/bar, seeks to the end of the file, appends some data and closes the file. It is more efficient to open the file once and for all:
while …; do echo $a; done >/tmp/bar
When there are multiple redirections happening at different times, calling
exec to perform redirections rather than wrapping a block in a redirection becomes useful.
while …; do echo $a; done
You'll find several other examples of redirection by browsing the
io-redirection tag on this site.