Bash snippets & functions : Yes / No question

bash shell

Introduction

One more post in the “Bash snippets and functions” series.

This one is about asking a Yes/No question in bash. This is a programming “grand classic“.
It might be used when asking for a user confirmation before starting a long or critical process. I show here different way for achieving this simple but important task ; I tried to keep it simple but efficient and robust.

I built this function over 5 goals :

  1. Simple and clear
  2. Easy to use and to understand
  3. Portable
  4. Not too long
  5. Not supposed to handle every option or feature that ever exist in this world

 

More “bash snippets & functions” posts

 

 

1 Using a while loop

I here use a while loop to ask and wait for a valid answer. This is a very common way to handle the Yes/No question problematic.
It could seems too complex for what it is, but this function is supposed to be portable and therefore needs to be well done.

Basically this is a while loop iterating on a “true” condition : this means that the loop will not stop until something force it to do so, we use the break command to do that. Based on the answer value we then return an exit code (“O” for an OK answer and “3” for a NO answer). We also set the default answer using the bash variable expansion property (${answer:=yes}).

This function may be used as any other well done function in a bash script : by using its exit code. We set the exit code value according to the answer as said above, then we would just have to set any action based on the $? value (line 51 …).
Please check the code for more details.

#!/bin/bash

# --------------------------------
# This is a demo script for a Yes No question function using a while loop
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#####################################
##### FUNCTIONS
#####################################

YesNoQuestion () {
  Usage="Usage : YesNoQuestion <Question> <default answer>"
  if (( "$#" != "2" )) ; then
    echo -e "${Usage}" && exit 1
  fi

  question="${1}"
  default="${2}"
  yes_RETVAL="0"
  no_RETVAL="3"
  RETVAL=""
  answer=""

  while true ; do
    read -p "${question} (${default}) ? " answer

    case ${answer:=${default}} in # This where we define (and use) the default value for $answer
      Y|y|YES|yes|Yes )
        RETVAL=${yes_RETVAL} && \
        break                  # This is how we get off the loop
      ;;
      N|n|NO|no|No )
        RETVAL=${no_RETVAL} && \
        break
      ;;
      * )
        echo "Please provide a valid answer (y or n)"   # Note the lack of "break" here
      ;;                                                #+ which keep us inside the loop
    esac                                                #+ until a valid answer if given

  done
  return ${RETVAL}
}

#####################################
##### MAIN
#####################################

echo "> entering script ..."
echo
YesNoQuestion "Do you like it" "yes"
Yesno_RETVAL="$?"
if [[ "${Yesno_RETVAL}" = "0" ]] ; then
  # run the YES action here
elif [[ "${Yesno_RETVAL}" = "3" ]] ; then
  # run the NO action here
else
  # error handling here
fi
echo
echo "> ... exiting script" && exit 0

 

2 Using a select statement

The advantage of a select statement is to limit to its smaller form the user input, this way you can avoid users to intentionally or not play with you script and try to break it. Select is not a security function ! but it can help you and the end-users to keep a script easy and cleaner.

There is one “big” difference between the previous while loop and this select loop : There is no default answer here. I could not find a good way to do that, if you know how to : please comment it out !

 

#!/bin/bash

# --------------------------------
# This is a demo script for a Yes No question function using a select loop
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#####################################
##### FUNCTIONS
#####################################
SelectYesNo () {

  Usage="Usage : SelectYesNo <Question> <default answer>"
  if (( "$#" != "2" )) ; then
    echo -e "${Usage}" && exit 1
  fi
  old_PS3="${PS3}"
  PS3='---> '
  question="${1}"
  default="${2}"
  yes_RETVAL="0"
  no_RETVAL="3"
  cancel_RETVAL="4"
  RETVAL=""
  answer=""

  echo "${question} ? (${default})"
  select answer in "Yes" "No" "Cancel"; do
    case ${answer} in
        Yes ) RETVAL="${yes_RETVAL}" && break
        ;;
        No ) RETVAL="${no_RETVAL}" && break
        ;;
        Cancel ) RETVAL="${cancel_RETVAL}" && exit ${cancel_RETVAL}
        ;;
        * ) echo "Please provide a valid answer (1,2 or 3)"
    esac
  done
  PS3="${old_PS3}"
  return ${RETVAL}
}

#####################################
##### MAIN
#####################################

echo "> entering script ..."
echo
SelectYesNo "Do you like it" "yes"
Yesno_RETVAL="$?"
if [[ "${Yesno_RETVAL}" = "0" ]] ; then
  echo "YES IN IF"
  # run the YES action here
elif [[ "${Yesno_RETVAL}" = "3" ]] ; then
  echo "NO IN IF"
  # run the NO action here
elif [[ "${Yesno_RETVAL}" = "4" ]] ; then
  echo "CANCEL IN IF"
  # run the NO action here
else
   echo "ERROR IN IF"
  # error handling here
fi
echo
echo "> ... exiting script" && exit 0

Leave a Reply

Your email address will not be published. Required fields are marked *

This site supports SyntaxHighlighter via WP SyntaxHighlighter. It can highlight your code.
How to highlight your code: Paste your code in the comment form, select it and then click the language link button below. This will wrap your code in a <pre> tag and format it when submitted.