How do I prompt for Yes/No/Cancel input in a Linux shell script?

后端 未结 30 1700
不思量自难忘°
不思量自难忘° 2020-11-22 04:52

I want to pause input in a shell script, and prompt the user for choices.
The standard Yes, No, or Cancel type question.
How d

相关标签:
30条回答
  • 2020-11-22 05:06

    I noticed that no one posted an answer showing multi-line echo menu for such simple user input so here is my go at it:

    #!/bin/bash
    
    function ask_user() {    
    
    echo -e "
    #~~~~~~~~~~~~#
    | 1.) Yes    |
    | 2.) No     |
    | 3.) Quit   |
    #~~~~~~~~~~~~#\n"
    
    read -e -p "Select 1: " choice
    
    if [ "$choice" == "1" ]; then
    
        do_something
    
    elif [ "$choice" == "2" ]; then
    
        do_something_else
    
    elif [ "$choice" == "3" ]; then
    
        clear && exit 0
    
    else
    
        echo "Please select 1, 2, or 3." && sleep 3
        clear && ask_user
    
    fi
    }
    
    ask_user
    

    This method was posted in the hopes that someone may find it useful and time-saving.

    0 讨论(0)
  • 2020-11-22 05:07

    I suggest you use dialog...

    Linux Apprentice: Improve Bash Shell Scripts Using Dialog

    The dialog command enables the use of window boxes in shell scripts to make their use more interactive.

    it's simple and easy to use, there's also a gnome version called gdialog that takes the exact same parameters, but shows it GUI style on X.

    0 讨论(0)
  • 2020-11-22 05:08

    Bash has select for this purpose.

    select result in Yes No Cancel
    do
        echo $result
    done
    
    0 讨论(0)
  • 2020-11-22 05:08

    You want:

    • Bash builtin commands (i.e. portable)
    • Check TTY
    • Default answer
    • Timeout
    • Colored question

    Snippet

    do_xxxx=y                      # In batch mode => Default is Yes
    [[ -t 0 ]] &&                  # If TTY => Prompt the question
    read -n 1 -p $'\e[1;32m
    Do xxxx? (Y/n)\e[0m ' do_xxxx  # Store the answer in $do_xxxx
    if [[ $do_xxxx =~ ^(y|Y|)$ ]]  # Do if 'y' or 'Y' or empty
    then
        xxxx
    fi
    

    Explanations

    • [[ -t 0 ]] && read ... => Call command read if TTY
    • read -n 1 => Wait for one character
    • $'\e[1;32m ... \e[0m ' => Print in green
      (green is fine because readable on both white/black backgrounds)
    • [[ $do_xxxx =~ ^(y|Y|)$ ]] => bash regex

    Timeout => Default answer is No

    do_xxxx=y
    [[ -t 0 ]] && {                   # Timeout 5 seconds (read -t 5)
    read -t 5 -n 1 -p $'\e[1;32m
    Do xxxx? (Y/n)\e[0m ' do_xxxx ||  # read 'fails' on timeout
    do_xxxx=n ; }                     # Timeout => answer No
    if [[ $do_xxxx =~ ^(y|Y|)$ ]]
    then
        xxxx
    fi
    
    0 讨论(0)
  • 2020-11-22 05:09

    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
        case $yn in
            ${yesptrn##^} ) make install; break;;
            ${noptrn##^} ) exit;;
            * ) echo "Answer ${yesword} / ${noword}.";;
        esac
    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.

    0 讨论(0)
  • 2020-11-22 05:10

    This is what I usually need in a script/function:

    • default answer is Yes, if you hit ENTER
    • accept also z (in case you mix up you are on QWERTZ Layout)
    • accept other lanyuages ("ja", "Oui", ...)
    • handle the right exit in case you are inside a function
    while true; do
        read -p "Continue [Y/n]? " -n 1 -r -e yn
        case "${yn:-Y}" in
            [YyZzOoJj]* ) echo; break ;;
            [Nn]* ) [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 ;; # handle exits from shell or function but don't exit interactive shell
            * ) echo "Please answer yes or no.";;
        esac
    done
    echo "and off we go!"
    
    0 讨论(0)
提交回复
热议问题