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

BashShellUnixBooleanOperators

Bash Problem Overview


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 ]

Bash Solutions


Solution 1 - Bash

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 - Bash

-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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVictor BrunellView Question on Stackoverflow
Solution 1 - BashJohn KugelmanView Answer on Stackoverflow
Solution 2 - BashBrad LanamView Answer on Stackoverflow