Sams Teach Yourself Shell Programming in 24 Hours
(Publisher: Macmillan Computer Publishing)
Author(s): Sriranga Veeraraghavan
ISBN: 0672314819
Publication Date: 01/01/99

Previous Table of Contents Next


Redirecting Two File Descriptors

You can redirect STDOUT and STDERR to a single file by using the general form for redirecting the output of one file descriptor to another:

n>&m

Here n and m are file descriptors (integers). If you let n=2 and m=1, you see that STDERR is redirected to STDOUT. By redirecting STDOUT to a file, you also redirect STDERR.

If m is a hyphen (-) instead of a number, the file corresponding to the file descriptor n is closed. When a file descriptor is closed, trying to read or write from it results in an error.

Reading Files, Another Look One of the most common uses of this form of redirection is for reading files one line at a time. You already looked at using a while loop to perform this task:

while read LINE
do
: # manipulate file here
done < file

The main problem with this loop is that it is executed in a subshell, thus changes to the script environment, such as exporting variables and changing the current working directory, does not apply to the script after the while loop changes. As an example, consider the following script:

#!/bin/sh
if [ -f "$1" ] ; then
    i=0
    while read LINE
    do
        i=‘echo "$i + 1" | bc’
    done < "$1"
    echo $i
fi

This script tries to count the number of lines in the file specified to it as an argument. Executing this script on the file

$ cat dirs.txt
/tmp
/usr/local
/opt/bin
/var

produces the following output:

0

Although you are incrementing the value of $i using the command

i=‘echo "$i + 1" | bc’

when the while loop exits, the value of $i is not preserved. In this case, you need to change a variable’s value inside the while loop and then use that value outside the loop. You can accomplish this by redirecting the STDIN prior to entering the loop and then restoring STDIN to the terminal after the while loop. The basic syntax is

exec n<&0 < file
while read LINE
do
: # manipulate file here
done
exec 0<&n n<&-

Here n is an integer greater than 2, and file is the name of the file you want to read. Usually n is chosen as a small number such as 3, 4, or 5.

As an example, you can construct a shell version of the cat command:

#!/bin/sh
if [ $# -ge 1 ] ; then
    for FILE in $@
    do
        exec 5<&0 < "$i"
        while read LINE ; do echo $LINE ; done
        exec 0<&5 5<&-
    done
fi

Summary

In this chapter, I formally introduced the concept of input and output. I covered the echo and printf commands that are used to produce messages from within shell scripts.

I also introduced output redirection, covering the methods of redirecting and appending the output of a command to a file. In addition, I discussed reading input for the first time. I also covered reading in files and reading input from users.

Finally, I introduced the concept of a file descriptor and showed several aspects of its use, including opening files for reading and writing, closing files, and redirecting the output of two file descriptors to one source.

In the subsequent chapters, I will expand on the material covered here, and you will see many more applications of both input and output redirection along with the use of file descriptors.

Questions

1.  Complete the script using the appropriate printf commands to perform the specified numeric conversions. Assume that the input is always a number:
#!/bin/sh

if [ $# -lt 2 ] ; then
    echo "ERROR: Insufficient arguments." ;
    exit 1 ;
fi

case "$1" in
    -o) : # convert the number stored in "$2" into octal
        ;;
    -x) : # convert the number stored in "$2" into hexadecimal
        ;;
    -e) : # convert the number stored in "$2" into scientific
⇒notation
        ;;
    *) echo "ERROR: Unknown conversion, $1!" ;;
esac
2.  Rewrite the error messages in the previous script to redirect their output to STDERR instead of STDOUT.

Terms

File Descriptor
An integer that is associated with a file. Enables you to read and write from a file using the integer instead of the file’s name.
STDIN
Standard Input. User input is read from STDIN. The file descriptor for STDIN is 0.
STDOUT
Standard Output. The output of scripts is usually to STDOUT. The file descriptor for STDOUT is 1.
STDERR
Standard Error. A special type of output used for error messages. The file descriptor for STDERR is 2.
Escape Sequence
An escape sequence is special sequence of characters that represents another character.
Output Redirection
In UNIX, the process of capturing the output of a command and storing it in a file is called output redirection because it redirects the output of a command into a file instead of the screen.
Input Redirection
In UNIX the process of sending input to a command from a file is called input redirection.


Previous Table of Contents Next