Last active

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Bash: General-purpose Yes/No prompt function ("ask")

View ask.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
# This is a general-purpose function to ask Yes/No questions in Bash, either
# with or without a default answer. It keeps repeating the question until it
# gets a valid answer.
 
ask() {
# http://djm.me/ask
while true; do
 
if [ "${2:-}" = "Y" ]; then
prompt="Y/n"
default=Y
elif [ "${2:-}" = "N" ]; then
prompt="y/N"
default=N
else
prompt="y/n"
default=
fi
 
# Ask the question
read -p "$1 [$prompt] " REPLY
 
# Default?
if [ -z "$REPLY" ]; then
REPLY=$default
fi
 
# Check if the reply is valid
case "$REPLY" in
Y*|y*) return 0 ;;
N*|n*) return 1 ;;
esac
 
done
}
 
 
# EXAMPLE USAGE:
 
if ask "Do you want to do such-and-such?"; then
echo "Yes"
else
echo "No"
fi
 
# Default to Yes if the user presses enter without giving an answer:
if ask "Do you want to do such-and-such?" Y; then
echo "Yes"
else
echo "No"
fi
 
# Default to No if the user presses enter without giving an answer:
if ask "Do you want to do such-and-such?" N; then
echo "Yes"
else
echo "No"
fi
 
# Only do something if you say Yes
if ask "Do you want to do such-and-such?"; then
said_yes
fi
 
# Only do something if you say No
if ! ask "Do you want to do such-and-such?"; then
said_no
fi
 
# Or if you prefer the shorter version:
ask "Do you want to do such-and-such?" && said_yes
 
ask "Do you want to do such-and-such?" || said_no

Yes ! - thank you.
This is just right - there are a lot of egos out there showing how 'clever' they are by making it over-complicated.
This does just what is required for a fn that prompts and can except Y or N as default, and the usage examples are clear

Hi,

This function is exactly what I needed.

But I'd also like to add a batch option for it.
So, if -B is set the ask function will not prompt and just use the default. Any advice how best do this?

Hi! Thanks alot for this function!

One thing you might like to fix: http://www.shellcheck.net/ reports that the keyword function is optional in bash and incompatible with other shells. Also, there should be brackets () after the function name.

Thanks!

I was working on something similar to this that included a timeout, and your snippet gave me some helpful inspiration. Thanks!

@dkirrane: I normally do something like this:

if [ "$1" = "-B" ]; then
  batch=true
else
  batch=false
fi

if $batch || ask "Prompt"; then
  # Do something
fi

Or if you're only asking one question:

if [ "$1" = "-B" ] || ask "Prompt"; then
  # Do something
fi

@swiftarrow - Updated, thanks

I've forked and made a minor amendment that you might want to include as a revision - it forces the use of /dev/tty (the controlling terminal) as the input to the read. That way, the function can be called within loops that use stdin for something else (like reading files).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.