Multiple expression if statement in BASH

It’s not very well documented, but it’s possible to include multiple conditional expressions in a single if statement in BASH. By multiple conditional expressions, I mean something like:

if foo = 1 or bar = 3 or abc = 4 then
    print Hello World
end if

You can do boolean OR in BASH by using the -o operator. The following is the above code written in BASH:

if [ $foo -eq 1 -o $bar -eq 3 -o $abc -eq 4 ]; then
    echo Hello World
fi

For boolean AND, use the -a operator. You can also intermix the two.

  1. David

    February 25, 2008 at 3:13 pm

    You can intermix the two, but how does it flow? IOW, if I say
    if [ $foo -eq 1 -o $bar -eq 1 -a $abc -eq 1 ]
    does that mean that either $foo or $bar can be 1 but $abc must be 1? Or does it mean that either $foo can be 1 or $bar and $abc can be 1?

  2. Tony

    August 5, 2008 at 1:23 pm

    Great help Ian!

    Another evaluation that might be hepful…
    Let say you supposed to have two environment variables $A and $B(A and B could be files as well), you want to know if those values are set or not, you can use
    if [ -z $A -a -z $B ];
    then
    echo “Please define A and B”
    fi

    this is useful when you have many conditions to evaluate

  3. Rechosen

    August 6, 2008 at 12:41 pm

    According to tldp.org, the -a (for and) operator has precedence over -o (for or), which means that -a is evaluated and processed before -o. The following experiment shows it:

    foo=1
    bar=2

    if [ $foo -eq 2 -a $bar -eq 2 -o $bar -eq 1 ]; then
    echo “Or has precedence.”
    else
    echo “And has precedence.”
    fi

    The above returns “And has precedence.”

  4. stef

    August 12, 2008 at 8:21 am

    I concur, the logical AND always has precedence before the logical OR. Basic math logic that you learn in high school 4th year i think.

    See ya!

  5. ben

    January 8, 2009 at 2:34 pm

    Thanks for putting this up… but to waste nearly an hour trying to figure it out myself from the docs?!?!?

    Is bash the ugliest, most inconsistent, ill thought out, kludged programming language the world has ever seen? – or is there worse?!?

  6. kannan

    February 12, 2009 at 10:04 pm

    The ‘if’ statement in bash has a built-in construct for this. Instead of the above, suggested, consider:

    if [ $foo -eq 1 ] || [ $bar -eq 3 ] || [$abc -eq 4 ]
    then
    echo “Hello World”
    fi

    With this construction, it’s possible to combine functional return values, like so:

    function check1() {

    }
    function check2() {

    }

    if [ $foo -eq 1 ] \
    || check1 $bar \
    || check2 $abs
    then
    echo “Hello World”
    fi

    I find this more flexible.

  7. zen

    April 22, 2009 at 9:16 pm

    @ben

    bash is not the “ugliest, most inconsistent, ill thought out, kludged programming language the world has ever seen”, it is a scripting language, designed to write scripts..

    bash can’t even be compared to ‘OOScripting’ type language like python or ruby. bash is for scripting. if you’re trying to use it for more than that, you’re sailing at your own peril!

  8. Michael

    May 15, 2009 at 10:14 am

    Sorry if this is obvious, I’m new to BASH. So what if you want: if a and (b or c). How do you force the OR to take precedence?

  9. quiescence

    May 27, 2009 at 9:32 am

    I’d do it this way:

    if (( (exprA) )) && (( (exprB) || (exprC) )); then

    fi

    Please, tell me if there are any redundant parentheses.

    Thank you in advance.

  10. Allen

    October 16, 2009 at 4:51 pm

    @Michael
    To force OR to take precedence you can use parentheses, but you have to escape them to avoid interpretation by the shell:

    $ j=1; i=3;
    $ if [ “$j” -eq 1 -a \( “$i” -eq 2 -o “$i” -eq 3 \) ]; then echo “True”; else echo “False”; fi
    true

    Alternatively, you could also use the [[ conditional command, a.k.a. the “modern” test:

    $ j=1; i=3;
    $ if [[ j -eq 1 && (i -eq 2 || i -eq 3) ]]; then echo “True”; else echo “False”; fi
    true

    The following two links helped me a lot:

    http://www.bash-hackers.org/wiki/doku.php/commands/classictest
    http://www.bash-hackers.org/wiki/doku.php/syntax/ccmd/conditional_expression

  11. ademcan

    January 11, 2012 at 6:12 am

    Thank you soo much. I have been looking for the solution for a while, I have tried || and && but it was not working.
    Your method is just so good :)