I want to pause input in a shell script, and prompt the user for choices.
The standard Yes
, No
, or Cancel
type question.
How do I accomplish this in a typical bash prompt?
In that case, we can simply wrap our yes/no prompt in a while loop. #!/bin/bash while true; do read -p "Do you want to proceed? (yes/no) " yn case $yn in yes ) echo ok, we will proceed; break;; no ) echo exiting...; exit;; * ) echo invalid response;; esac done echo doing stuff...
By default, `yes` command repeats the character 'y' if no string value is specified with this command. When `yes` command uses with pipe and another command then it will send the value 'y' or `yes` for any confirmation prompt. This command can help to save time by doing many confirmation tasks automatically.
This can actually be done with a single line using the set builtin command with the -e option. Putting this at the top of a bash script will cause the script to exit if any commands return a non-zero exit code.
Linux exit command is used to exit from the current shell. It takes a parameter as a number and exits the shell with a return of status number. If we did not provide any parameter, it would return the status of the last executed command. The exit command closes a script and exits the shell.
The simplest and most widely available method to get user input at a shell prompt is the read
command. The best way to illustrate its use is a simple demonstration:
while true; do read -p "Do you wish to install this program? " yn case $yn in [Yy]* ) make install; break;; [Nn]* ) exit;; * ) echo "Please answer yes or no.";; esac done
Another method, pointed out by Steven Huwig, is Bash's select
command. Here is the same example using select
:
echo "Do you wish to install this program?" select yn in "Yes" "No"; do case $yn in Yes ) make install; break;; No ) exit;; esac done
With select
you don't need to sanitize the input – it displays the available choices, and you type a number corresponding to your choice. It also loops automatically, so there's no need for a while true
loop to retry if they give invalid input.
Also, Léa Gris demonstrated a way to make the request language agnostic in her answer. Adapting my first example to better serve multiple languages might look like this:
set -- $(locale LC_MESSAGES) yesptrn="$1"; noptrn="$2"; yesword="$3"; noword="$4" while true; do read -p "Install (${yesword} / ${noword})? " yn if [[ "$yn" =~ $yesexpr ]]; then make install; exit; fi if [[ "$yn" =~ $noexpr ]]; then exit; fi echo "Answer ${yesword} / ${noword}." done
Obviously other communication strings remain untranslated here (Install, Answer) which would need to be addressed in a more fully completed translation, but even a partial translation would be helpful in many cases.
Finally, please check out the excellent answer by F. Hauri.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With