Bash Scripting – Reading user inputs
Although providing command line options and parameters is a great way to get data from your script users, sometimes your script needs to be more interactive. Sometimes you need to ask a question while the script is running and wait for a response from the person running your script. The bash shell provides the read command just for this purpose.
The read command accepts input either from standard input (such as from the keyboard) or from another file descriptor. After receiving the input, the read command places the data into a variable. Here’s the read command at its simplest:
$ cat test21.sh #!/bin/bash # testing the read command # echo -n “Enter your name: ” read name echo “Hello $name, welcome to my program. ” # $ $ ./test21.sh Enter your name: unixadminschool com Hello unixadminschool com, welcome to my program. $
That’s pretty simple. Notice that the echo command that produced the prompt uses the -n option. This suppresses the newline character at the end of the string, allowing the script user to enter data immediately after the string, instead of on the next line. This gives your scripts a more form-like appearance.
$ cat test22.sh #!/bin/bash # testing the read -p option # read -p “Please enter your age: ” age days=$[ $age * 365 ] echo “That makes you over $days days old! ” # $ $ ./test22.sh Please enter your age: 10 That makes you over 3650 days old! $
You’ll notice in the first example that when a name was entered, the read command assigned both the first name and last name to the same variable. The read command assigns all data entered at the prompt to a single variable, or you can specify multiple variables. Each data value entered is assigned to the next variable in the list. If the list of variables runs out before the data does, the remaining data is assigned to the last variable:
$ cat test23.sh #!/bin/bash # entering multiple variables # read -p “Enter your name: ” first last echo “Checking data for $last, $first…” $ $ ./test23.sh Enter your name: unixadminschool Blum Checking data for Blum, unixadminschool… $
$ cat test24.sh #!/bin/bash # Testing the REPLY Environment variable # read -p “Enter your name: ” echo echo Hello $REPLY, welcome to my program. # $ $ ./test24.sh Enter your name: Christine Hello Christine, welcome to my program. $
Be careful when using the read command. Your script may get stuck waiting for the script user to enter data. If the script must go on regardless of whether any data was entered, you can use the -t option to specify a timer. The -t option specifies the number of seconds for the read command to wait for input. When the timer expires, the read command returns a non-zero exit status:
$ cat test25.sh #!/bin/bash # timing the data entry # if read -t 5 -p “Please enter your name: ” name then echo “Hello $name, welcome to my script” else echo echo “Sorry, too slow! ” fi $ $ ./test25.sh Please enter your name: unixadminschool Hello unixadminschool, welcome to my script $ $ ./test25.sh Please enter your name: Sorry, too slow! $
Because the read command exits with a non-zero exit status if the timer expires, it’s easy to use the standard structured statements, such as an if-then statement or a while loop to track what happened. In this example, when the timer expires, the if statement fails, and the shell executes the commands in the else section.
Instead of timing the input, you can also set the read command to count the input characters. When a preset number of characters has been entered, it automatically exits, assigning the entered data to the variable:
$ cat test26.sh #!/bin/bash # getting just one character of input # read -n1 -p “Do you want to continue [Y/N]? ” answer case $answer in Y | y) echo echo “fine, continue on…”;; N | n) echo echo OK, goodbye exit;; esac echo “This is the end of the script” $ $ ./test26.sh Do you want to continue [Y/N]? Y fine, continue on… This is the end of the script $ $ ./test26.sh Do you want to continue [Y/N]? n OK, goodbye $
This example uses the -n option with the value of 1, instructing the read command to accept only a single character before exiting. As soon as you press the single character to answer, the read command accepts the input and passes it to the variable. You don’t need to press the Enter key.
Sometimes you need input from the script user, but you don’t want that input to display on the monitor. The classic example is when entering passwords, but there are plenty of other types of data that you need to hide.
The -s option prevents the data entered in the read command from being displayed on the monitor; actually, the data is displayed, but theread command sets the text color to the same as the background color. Here’s an example of using the -s option in a script:
$ cat test27.sh #!/bin/bash # hiding input data from the monitor # read -s -p “Enter your password: ” pass echo echo “Is your password really $pass? ” $ $ ./test27.sh Enter your password: Is your password really T3st1ng? $
Finally, you can also use the read command to read data stored in a file on the Linux system. Each call to the read command reads a single line of text from the file. When no more lines are left in the file, the read command exits with a non-zero exit status.
The tricky part is getting the data from the file to the read command. The most common method is to pipe the result of the cat command of the file directly to a while command that contains the read command. Here’s an example:
$ cat test28.sh #!/bin/bash # reading data from a file # count=1 cat test | while read line do echo “Line $count: $line” count=$[ $count + 1] done echo “Finished processing the file” $ $ cat test The quick brown dog jumps over the lazy fox. This is a test, this is only a test. O Romeo, Romeo! Wherefore art thou Romeo? $ $ ./test28.sh Line 1: The quick brown dog jumps over the lazy fox. Line 2: This is a test, this is only a test. Line 3: O Romeo, Romeo! Wherefore art thou Romeo? Finished processing the file $