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 LNAMEwhere 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. ThomasYou 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: _
while read VARIABLE do do something with $VARIABLE doneDuring 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_specwhere 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 pebblesand 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: pebblesand 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_specThus 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 lineThe actual method of obtaining the filename for input redirection to the while-read command will depend upon your specific circumstances.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
©2023, Mark A. Thomas. All Rights Reserved.