IN THIS CHAPTER
In this chapter you'll learn how to read data from the terminal or from a file using the read
command and how to print formatted data to standard output using the printf
command.
The general format of the read
command is
read variables
When this command is executed, the shell reads a line from standard input and assigns the first word read to the first variable listed in variables, the second word read to the second variable, and so on. If there are more words on the line than there are variables listed, the excess words get assigned to the last variable. So for example, the command
read x y
reads a line from standard input, storing the first word read in the variable x
, and the remainder of the line in the variable y
. It follows from this that the command
read text
reads and stores an entire line into the shell variable text
.
Let's put the read
command to work. We'll write a simplified version of the cp
command that will be a bit more user friendly than the standard Unix one. We'll call it mycp
, and we'll have it take two arguments: the source file and the destination file. If the destination file already exists, we'll tell the user and then ask him (or her) if he wants to proceed with the copy. If the answer is “yes,” we'll go ahead with it; otherwise, we won't.
$ cat mycp
#
# Copy a file
#
if [ "$#" -ne 2 ]
then
echo "Usage: mycp from to"
exit 1
fi
from="$1"
to="$2"
#
# See if the destination file already exists
#
if [ -e "$to" ]
then
echo "$to already exists; overwrite (yes/no)?"
read answer
if [ "$answer" != yes ]
then
echo "Copy not performed"
exit 0
fi
fi
#
# Either destination doesn't exist or "yes" was typed
#
cp $from $to # proceed with the copy
$
$ ls What files are around? addresses intro lotsaspaces mycp names nu numbers phonebook stat $ mycp No arguments Usage: mycp from to $ mycp names names2 Make a copy of names $ ls -l names* Did it work? -rw-r--r-- 1 steve steve 43 Jul 20 11:12 names -rw-r--r-- 1 steve steve 43 Jul 21 14:16 names2 $ mycp names numbers Try to overwrite an existing file numbers already exists; overwrite (yes/no)? no Copy not performed $
To complete the test cases, try answering yes and ensuring that the program proceeds with the copy.
There are a few things worthy of mention with the mycp
program. First, if the file already exists, the echo
command that prompts for the yes/no response is executed. The read
command that follows causes the shell to wait for you to type something in. Note that the shell does not prompt you when it's waiting for you to enter data; it's up to you to add your own prompt message to the program.
The data that is typed is stored in the variable answer
and is then tested against the characters “yes” to determine whether the copy is to proceed. The quotes around answer
in the test
[ "$answer" != yes]
are necessary in case the user just presses the Enter key without typing any data. In that case, the shell would store a null value in answer
, and test
would issue an error message if the quotes were omitted.
A slight annoyance with mycp
is that after the echo
command is executed to alert the user that the file already exists, the response that is typed by the user appears on the next line. This happens because the echo
command always automatically displays a terminating newline character after the last argument.
This can be suppressed if the last two characters given to echo
are the special escape characters c
. This tells echo
to leave the cursor right where it is after displaying the last argument and not to go to the next line. So if you changed the echo
command in mycp
to read like this:
echo "$to already exists; overwrite (yes/no)? c"
the user's input would be typed right after the message on the same line. Bear in mind that the c
is interpreted by echo
and not by the shell, meaning that it must be quoted so that the backslash makes it to echo
.
echo
interprets other special characters. These must each be preceded by a backslash. They're summarized in Table 10.1.