alyms108
alyms108

Reputation: 51

Testing for Inequality Doesn't Work

CONFIRM=""

echo "Do you want to backup your home directory? Please enter y|Y or n|N"

read CONFIRM;
if [[ "$CONFIRM" != "Y" ]] || [[ "$CONFIRM" != "y" ]]; then
  echo "The backup will not run. Aborting now..."
else
  echo "The backup will run now. Backing up to $DEST"
  # more code
fi

Whenever I enter "y" or "Y", the condition under else should be executed. Instead, the condition under if gets executed no matter what I enter. I've tried multiple combinations of square brackets and quoting I can think of, but nothing works. Why doesn't the else branch correctly execute?

Upvotes: 0

Views: 68

Answers (3)

Mike Q
Mike Q

Reputation: 7327

Another example, I ensure we don't continue until we get specifically y/n/q as inputs. using -p -n1 removes the need to press enter. In summary: a case statement, reads the one keypress, lowercase checking etc ... This example allows for yes/no or quit.

typeset confirm=''
while true; do
    read -p "Select (y/n/q) ?" -n1 confirm
    case ${confirm,,} in
        y|n|q) break;;
        *) echo "Answer y for yes / n for no  or q for quit.";;
    esac
done
echo -e "\nAnswer = $confirm" ;sleep 2

if [[ "${confirm,,}" == "q" ]] ; then
        echo "OK Quitting.."
        exit 0
fi

if [[ "${confirm,,}" == "y" ]] ; then
        echo "Continuing ..."
else
        echo "No? Do something else etc.. "
fi

Upvotes: 0

Rene Knop
Rene Knop

Reputation: 1836

If we look closely at the prompt "Please enter y | Y or n | N", then there is a third case missing, that handles invalid input. Together with @cdarke's answer, this results e.g. in the following short condition:

CONFIRM=""

echo "Do you want to backup your home directory? Please enter y|Y or n|N"

read CONFIRM;
if [[ "$CONFIRM" = [Yy] ]]; then
  echo "The backup will run now. Backing up to $DEST"
  # more code
elif [[ "$CONFIRM" = [Nn] ]]; then
  echo "The backup will not run. Aborting now..."
else
  echo "Wrong Input. Please enter y|Y or n|N."
fi

Upvotes: 1

ruakh
ruakh

Reputation: 183371

This:

[[ "$CONFIRM" != "Y" ]] || [[ "$CONFIRM" != "y" ]]

means "$CONFIRM isn't Y or $CONFIRM isn't y". That is always guaranteed to be true:

  • if $CONFIRM is Y, then it's not y, so the second option is true
  • if $CONFIRM is y, then it's not Y, so the first option is true
  • if $CONFIRM is anything else, then both options are true

To fix this, you need to use && ("and") instead of || ("or"):

[[ "$CONFIRM" != Y ]] && [[ "$CONFIRM" != y ]]

which, by De Morgan's laws, is equivalent to this:

! { [[ "$CONFIRM" = Y ]] || [[ "$CONFIRM" = y ]] ; }

Upvotes: 3

Related Questions