Boolean operators ( &&, -a, ||, -o ) in Bash

157,147

Solution 1

Rule of thumb: Use -a and -o inside square brackets, && and || outside.

It's important to understand the difference between shell syntax and the syntax of the [ command.

  • && and || are shell operators. They are used to combine the results of two commands. Because they are shell syntax, they have special syntactical significance and cannot be used as arguments to commands.

  • [ is not special syntax. It's actually a command with the name [, also known as test. Since [ is just a regular command, it uses -a and -o for its and and or operators. It can't use && and || because those are shell syntax that commands don't get to see.

But wait! Bash has a fancier test syntax in the form of [[ ]]. If you use double square brackets, you get access to things like regexes and wildcards. You can also use shell operators like &&, ||, <, and > freely inside the brackets because, unlike [, the double bracketed form is special shell syntax. Bash parses [[ itself so you can write things like [[ $foo == 5 && $bar == 6 ]].

Solution 2

-a and -o are the older and/or operators for the test command. && and || are and/or operators for the shell. So (assuming an old shell) in your first case,

[ "$1" = 'yes' ] && [ -r $2.txt ]

The shell is evaluating the and condition.

In your second case,

[ "$1" = 'yes' -a $2 -lt 3 ]

The test command (or builtin test) is evaluating the and condition.

Of course in all modern or semi-modern shells, the test command is built in to the shell, so there really isn't any or much difference.

In modern shells, the if statement can be written:

[[ $1 == yes && -r $2.txt ]]

Which is more similar to modern programming languages and thus is more readable.

Share:
157,147
Victor Brunell
Author by

Victor Brunell

Updated on July 05, 2022

Comments

  • Victor Brunell
    Victor Brunell almost 2 years

    What is the difference between the &&, ||, -a, and -o Unix operators?

    What are the restrictions on the usage of both types?

    Is it simply that the && and || operators should be used when using flags in the condition?

    As in:

    [ "$1" = "yes" ] && [ -r $2.txt ]
    

    versus:

    [ "$1" = "yes" -a $2 -lt 3 ]
    
  • Victor Brunell
    Victor Brunell over 10 years
    So -a and -o are not exactly necessary if you just use the [[ form? Are there any advantages of using [[ $foo == 5 && $bar == 6 ]] vs [ $foo == 5 -a $bar == 6 ]?
  • Victor Brunell
    Victor Brunell over 10 years
    Does this mean the single bracket [ form is deprecated in favor of the [[ form?
  • janos
    janos over 10 years
    Yes, it seems the -o and -a flags are deprecated in the standard. They will probably continue to work for a long time, but it's good to be prepared for the future.
  • Brad Lanam
    Brad Lanam over 10 years
    The [[ form is much easier to use -- it handles many quoting problems. e.g. in the example, $1 can be left unquoted, even if it may be empty.
  • Brad Lanam
    Brad Lanam over 10 years
    It depends on whether you need to support older shells. All modern OSs have either bash (in /bin (linux), /usr/bin/ or elsewhere) or /usr/bin/ksh which support the [[ form.
  • chepner
    chepner over 10 years
    The suggested POSIX-compatible replacement for -a is two separate calls to test joined with &&: [ expr1 -a expr2 ] becomes [ expr1 ] && [ expr2 ]. Similarly for -o and ||.
  • Étienne
    Étienne almost 9 years
    @BradLanam Even modern embedded systems typically do not have bash or ksh.