How to prompt and read user input in a Bash shell script

Unix/Linux bash shell script FAQ: How do I prompt a user for input from a shell script (Bash shell script), and then read the input the user provides?

Answer: I usually use the shell script read function to read input from a shell script. Here are two slightly different versions of the same shell script. This first version prompts the user for input only once, and then dies if the user doesn't give a correct Y/N answer:

# (1) prompt user, and read command line argument
read -p "Run the cron script now? " answer

# (2) handle the command line argument we were given
while true
do
  case $answer in
   [yY]* ) /usr/bin/wget -O - -q -t 1 http://www.example.com/cron.php
           echo "Okay, just ran the cron script."
           break;;

   [nN]* ) exit;;

   * )     echo "Dude, just enter Y or N, please."; break ;;
  esac
done

This second version stays in a loop until the user supplies a Y/N answer:

while true
do
  # (1) prompt user, and read command line argument
  read -p "Run the cron script now? " answer

  # (2) handle the input we were given
  case $answer in
   [yY]* ) /usr/bin/wget -O - -q -t 1 http://www.example.com/cron.php
           echo "Okay, just ran the cron script."
           break;;

   [nN]* ) exit;;

   * )     echo "Dude, just enter Y or N, please.";;
  esac
done

I prefer the second approach, but I thought I'd share both of them here. They are subtly different, so not the extra break in the first script.

This Linux Bash 'read' function is nice, because it does both things, prompting the user for input, and then reading the input. The other nice thing it does is leave the cursor at the end of your prompt, as shown here:

Run the cron script now? _

(This is so much nicer than what I had to do years ago.)

Prompting/reading shell script input, and the Bash shell read function

An easy way to find documentation on this Bash shell read function is to type this man command:

man read

I wouldn't normally show that, but invoking man like this brings up the "Bash builtins" man page, instead of the normal Bash shell man page, and in this case, this documentation is more of what you need.

For your reference, here is the Bash shell "read" documentation from that man page:

read [-ers] [-u fd] [-t timeout] [-a aname] [-p prompt] [-n nchars] [-d delim] [name ...]
       
One line is read from the standard input, or from the file descriptor fd 
supplied as an argument to the -u option, and the first word is assigned 
to the first name, the second word to the second name, and so on, with 
leftover words and their intervening separators assigned to the last name.  
If there are fewer words read from the input stream than names, the remaining 
names are assigned empty values. The characters in IFS are used to split the 
line into words. The backslash character (\) may be used to remove any special 
meaning for the next character read and for line continuation. Options, 
if supplied, have the following meanings:

-a aname
   The words are assigned to sequential indices of the array variable aname, 
   starting at 0. aname is unset before any new values are
   assigned. Other name arguments are ignored.

-d delim
   The first character of delim is used to terminate the input line, rather 
   than newline.

-e If the standard input is coming from a terminal, readline (see READLINE above) 
   is used to obtain the line.

-n nchars
   read returns after reading nchars characters rather than waiting for a complete 
   line of input.

-p prompt
   Display prompt on standard error, without a trailing newline, before attempting 
   to read any input. The prompt is displayed only if input is coming from a terminal.

-r Backslash does not act as an escape character. The backslash is considered to 
   be part of the line. In particular, a backslash-newline pair may not be used as 
   a line continuation.

-s Silent mode. If input is coming from a terminal, characters are not echoed.

-t timeout
   Cause read to time out and return failure if a complete line of input is not 
   read within timeout seconds.  This option has no effect if read is not reading 
   input from the terminal or a pipe.

-u fd Read input from file descriptor fd.

If no names are supplied, the line read is assigned to the variable REPLY. 
The return code is zero, unless end-of-file is encountered, 
read times out, or an invalid file descriptor is supplied as the argument to -u.

Summary: How to read Bash script command line arguments

I hope this example of how to read shell script command line arguments has been helpful. As you can see, knowing about the Bash read function, and also knowing the Bash shell case function, are both important in this solution.