Boolean operators ( &&, -a, ||, -o ) in Bash
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 astest
. 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.
Victor Brunell
Updated on July 05, 2022Comments
-
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 over 10 yearsSo -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 over 10 yearsDoes this mean the single bracket [ form is deprecated in favor of the [[ form?
-
janos over 10 yearsYes, 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 over 10 yearsThe [[ 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 over 10 yearsIt 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 over 10 yearsThe suggested POSIX-compatible replacement for
-a
is two separate calls totest
joined with&&
:[ expr1 -a expr2 ]
becomes[ expr1 ] && [ expr2 ]
. Similarly for-o
and||
. -
Étienne almost 9 years@BradLanam Even modern embedded systems typically do not have bash or ksh.