Program Input


Program Input Using Read

Up to this point, we have discussed a single technique for getting user data values into a shell program, specifically using positional parameters. Another technique to get input values into a program is by using the read command. The general format of the read command is:

	read VARIABLE(S)
When this command is executed, the shell reads a single line from standard input and assigns the first item to the first variable, the second item to the second variable, and so on. Thus if you wish to read a single item (such as the users name), you can do the following:
	$ read NAME [Enter]
	_
Note at this point, the cursor will remain on next line, waiting for the user to enter a value. We could then create a short script to do this as follows:

#!/bin/ksh

# program name: hello1

echo -n "Please enter your name: " 
read NAME 
echo "Hello $NAME! How are you today?" 

You can also read more than one data item at a time as follows:

	read FNAME LNAME
where the first item on the standard input line would be assigned to FNAME and the second item on the line would be assigned to LNAME. However, if more than two pieces of data (separated by spaces) were present on the line, the first item would be assigned to the first variable and all subsequent data items would be assigned to the second variable, as follows:
	$ read FNAME LNAME [Enter]
	Mark A. Thomas [Enter]
	$ echo $LNAME [Enter]
	A. Thomas
You can also combine use of the read statement with the use of positional paramters based upon the way the user has invoked the program. Thus you can check for the presence of positional parameters, and if present, use them as input data. If positional parameters are not present, you can prompt the user for input data and use the read command to "get" the data values. Observe the following shell program example:

#!/bin/sh
	
# program name: hello2

if [ $# -eq 0 ]		# if no args on command line, prompt for input  
then
     echo -n "\nPlease enter your name: "
     read NAME
else
     NAME=$1
fi
echo "Hello $NAME! How are you today?"

In the above program example, the user can include a name on the command line if they wish, or if not, they will be prompted as follows:

	$ hello fred [Enter]
	Hello fred! How are you today?

	$ hello [Enter]
	Please enter your name: _

Using Read With Redirection

Frequently you will find the need to get input from a data file where you will wish to read a single line (i.e. record) at a time. You can do this with a combination of the while and the read commands with syntax as follows:
	while read VARIABLE
	do
	    do something with $VARIABLE
	done
During each iteration of the while loop, the VARIABLE will be assigned a line (terminated by a carriage return/line feed) from the standard input, until an end of file character ([Ctrl-d]). The simplest way to read data from a file is using input redirection as follows:
	script_name < file_spec
where script_name is the name of the script to process each line and file_spec is the name of the data file. Consider the following shell script:

#!/bin/sh

# program name: make_backup

while read LINE
do
    echo "Backing up file: $LINE" 
    mv $LINE ${LINE}.backup
done

In this example, the variable following the read command has been named LINE, to indicate it is storing a line from a file (note this is just a user defined variable name, nothing special). This script will read filenames from a file until the end of the file has been reached, in which case the read will return a non-zero status and the while will terminate. After reading a filename, the script will then rename the filename (stored in $LINE) to filename.backup. So if we had a data file named flintones which contained the following file names (and assuming the files existed):

	fred
	wilma
	pebbles
and we ran the above program as follows, we would see:
	$ make_backup < flintstones [Enter]
	Backing up file: fred
	Backing up file: wilma
	Backing up file: pebbles
and this would result in creation of fred.backup, wilma.backup, and pebbles.backup.

Note that this requires the user to understand the concept of input redirection and know how to use the redirection operator, which may be a bit much for a novice user. A different approach is to use the redirection operator from within the script and in conjunction with the while-read statement. Syntactically this is accomplished by including the redirection operator following the done statement (many find this awkward, but that is how it works) as follows:

	done < file_spec
Thus the above script could be modified as follows:

#!/bin/sh

# program name: make_backup

while read LINE
do
    echo "Backing up file: $LINE" 
    mv $LINE ${LINE}.backup
done < flintstones

Note that this script will now only work for one input file, specifically the file "flintstones." A better solution in this case (but not always) may be something like:

	done < $1		# get input file from the command line

where the script would then be run as follows:

make_backup flintstones or done < $INPUT_FILE # get input file from a user variable

where you would add the following two lines before the while-read:

echo -n "Enter the input file name: " read INPUT_FILE

The actual method of obtaining the filename for input redirection to the while-read command will depend upon your specific circumstances.

Command Summary




©2023, Mark A. Thomas. All Rights Reserved.