Skip to content

Bash logical operators

Logical Operators Cover

Logical operators (AND, OR and NOT) serve multiple purposes in bash. First and foremost, they are used to create complex expressions by combining simpler ones. Depending on the version of test and bash in use the syntax of logical operators might change. Logical operators are instrumental in flow control for decision-making and command execution based on complex expressions’ results.

Similar to other programming languages the logical operators in bash are:

  • AND (&& or -a): Returns true only of both operands are true
  • OR (|| or -o): Returns true if at least one operand is true
  • Not Equal (!): Inverts the value of the operand

Let us look at a simple example of using logical operators:

#!/bin/bash

echo "Please enter your number: "
read NUM

if [[ $NUM =~ ^[0-9]+$ ]]; then
    echo "The value you entered is a number"
fi

if [ -z "$NUM" ]; then
    echo "The number is empty!."
    exit 1
fi  

if [ $NUM -gt 0 -a $NUM -lt 50 ]; then
    echo "The num ${NUM} is greater than zero AND less than 50"
else
    echo "The num ${NUM} is less than zero, zero or greater than 50"
fi

if [ $((NUM % 2)) -eq 0 -o $((NUM % 3)) -eq 0 ]; then
    echo "The num ${NUM} is either visible by 2 or 3."
else 
    echo "The num ${NUM} is not divisible by 2 or 3."
fi

One thing to note here is that we’re using bash in order to evaluate regular expressions, because the [[ ]] syntax (line 6) is built into bash and is not available for other shells. In order to run this script either put the shebang – #!/bin/bash line of code at the beginning or run your file with bash by typing bash yourfile in your terminal.

If you notice in the code snippet above we didn’t use AND, OR and NOT, and the reason for that is that regular test uses a different syntax for operators. Actually, behind the scenes it uses the same operators, the only difference is the syntax. So instead of AND we have -a, instead of OR we have -o and instead of NOT we have !.

Let us see how the same file is rewritten using the more recent version of test.

#!/bin/bash

echo "Please enter your number: "
read NUM

if ! [[ $NUM =~ ^[0-9]+$ ]]; then
    echo "The value you entered is NOT a number"
    exit 1
else
    echo "The value you entered is a number"
fi

if [ -z "$NUM" ]; then
    echo "The number is empty!."
    exit 1
fi  

if [[ $NUM -gt 0 && $NUM -lt 50 ]]; then
    echo "The num ${NUM} is greater than zero AND less than 50"
else
    echo "The num ${NUM} is less than zero, zero or greater than 50"
fi

if [[ $((NUM % 2)) -eq 0 || $((NUM % 3)) -eq 0 ]]; then
    echo "The num ${NUM} is either visible by 2 or 3."
else 
    echo "The num ${NUM} is not divisible by 2 or 3."
fi

The only difference between the first snippet and the second is the version of test used and the syntax of the logical operators. We used single brackets [ ] and old operators such as -a and -o in the first snippet. On the other hand, we used shell operators && and || in the more expressive form of test, [[ ]].

The results will be the same. The only difference here is that the new version of test has built-in capabilities for regex matching. On the other hand double brackets are not POSIX compliant and thus might not work in projects that are required to be backwards compatible.