How to prompt for yes or no in bash?

14,270

Solution 1

I like to use the following function:

function yes_or_no {
    while true; do
        read -p "$* [y/n]: " yn
        case $yn in
            [Yy]*) return 0  ;;  
            [Nn]*) echo "Aborted" ; return  1 ;;
        esac
    done
}

So in your script you can use like this:

yes_or_no "$message" && do_something

In case the user presses any key other than [yYnN] it will repeat the message.

Solution 2

This works too:

read -e -p "Do you like pie? " choice
[[ "$choice" == [Yy]* ]] && echo "doing something" || echo "that was a no"

Pattern starting with Y or y will be taken as yes.

Solution 3

I like Jahid's oneliner. Here is a slight simplification of it:

[[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]]

Here are some tests:

$ [[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping

Continue? [y/N]> yes
Continuing

$ for test_string in y Y yes YES no ''; do echo "Test String: '$test_string'"; echo $test_string | [[ "$(read -e -p 'Continue? [y/N]>'; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping; done

Test String: 'y'
Continuing

Test String: 'Y'
Continuing

Test String: 'yes'
Continuing

Test String: 'YES'
Continuing

Test String: 'no'
Stopping

Test String: ''
Stopping

Solution 4

This works:

echo "Do you like pie?"
read pie
if [[ $pie == y* ]]; then
    echo "You do! Awesome."
else
    echo "I don't like it much, either."
fi

[[ $pie == y* ]] tests to see of the variable $pie starts with y.

Feel free to make this better if you'd like.

Solution 5

In contrast to the other answers this function gives you the possibility to set a default:

function askYesNo {
        QUESTION=$1
        DEFAULT=$2
        if [ "$DEFAULT" = true ]; then
                OPTIONS="[Y/n]"
                DEFAULT="y"
            else
                OPTIONS="[y/N]"
                DEFAULT="n"
        fi
        read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT
        INPUT=${INPUT:-${DEFAULT}}
        echo ${INPUT}
        if [[ "$INPUT" =~ ^[yY]$ ]]; then
            ANSWER=true
        else
            ANSWER=false
        fi
}

askYesNo "Do it?" true
DOIT=$ANSWER

if [ "$DOIT" = true ]; then
    < do some stuff >
fi

On the command line you would see

Do it? [Y/n] y
Share:
14,270
Ben Aubin
Author by

Ben Aubin

Updated on June 14, 2022

Comments

  • Ben Aubin
    Ben Aubin almost 2 years

    How do I ask a yes/no type question in Bash?

    I ask the question... echo "Do you like pie?"

    And receive the answer... read pie

    How do I do something if the answer is yes, or starts with y (so yes and yeah, etc, will work too).

  • Etan Reisner
    Etan Reisner about 9 years
    read -p "$@ [y/n]: " is incorrect, you need to use $* or the read will explode if the function is called with more than one argument. Also, technically this should use yes_or_not "$@" but for this that only matters if you use yes_or_not 'foo bar' and then the user doesn't input yes or no (the inner spaces will then get lost).
  • Ben Aubin
    Ben Aubin about 9 years
    That's pretty awesome :)
  • phyatt
    phyatt almost 4 years
    I added a question mark after the $* ... This also works great with an if block: if yes_or_no "Do next task"; then ;;;; fi constructs
  • twhitney
    twhitney about 2 years
    What are the reasons to include the -e and -p flags out of curiosity?
  • Jahid
    Jahid about 2 years
    @twhitney see read --help for details.
  • Akhil
    Akhil almost 2 years
    this only works on bash read not zsh read.
  • Bruno Bronosky
    Bruno Bronosky almost 2 years
    @Akhil I added a zsh example for you. ☮️❤️🌈
  • Akhil
    Akhil almost 2 years
    appending ? worked for me in zsh. i.e. [[ "$(read -e '?Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]] ref: superuser.com/questions/555874/…