Confusing use of && and || operators
I was skimming through an
/etc/rc.d/init.d/sendmailfile (I know this is hardly ever used, but I'm studying for an exam), and I've become a bit confused about the
||operators. I've read where they can be used in statements such as:
if [ test1 ] && [ test2 ]; then echo "both tests are true" elif [ test1 ] || [ test2 ]; then echo "one test is true" fi
However, this script shows single line statements such as:
[ -z "$SMQUEUE" ] && SMQUEUE="QUEUE" [ -f /usr/sbin/sendmail ] || exit 0
These seem to be using the
||operators to elicit responses based on tests, but I haven't been able to dig up documenation regarding this particular use of these operators. Can anyone explain what these do in this particular context?
The right side of
&&will only be evaluated if the exit status of the left side is zero (i.e. true).
||is the opposite: it will evaluate the right side only if the left side exit status is non-zero (i.e. false).
You can consider
[ ... ]to be a program with a return value. If the test inside evaluates to true, it returns zero; it returns nonzero otherwise.
$ false && echo howdy! $ true && echo howdy! howdy! $ true || echo howdy! $ false || echo howdy! howdy!
If you do
which [, you might see that
[actually does point to a program! It's usually not actually the one that runs in scripts, though; run
type [to see what actually gets run. If you wan to try using the program, just give the full path like so:
/bin/[ 1 = 1.
When you see "X or Y", you test X. If it's true, you already know the answer to "X or Y" (it's true), so no need to test Y. If it's true, you don't know the answer to "X or Y", so you do need to test Y. When you see "X and Y", you test X. If it's false, you already know the answer to "X and Y" (it's false), so no need to test Y. If X is true, then you do need to test Y to see if "X and Y" is true.
Instead of "if the left side returns zero", I would write "if the left side command's exit status is zero". I find "return" a bit ambiguous as the output and the exit status can both be considered as "return values"
Not only can you "_consider_ `[ ... ]` to be a program", in many cases it **_is_**. It's commonly in the file `/bin/[` or `/usr/bin/[`.
C programmers will find this super confusing. There 0 means false... While in shellscripting 0 means true... Mind blown.
Another one that you could mention is `test` instead of `if` or ``. And `if [` and `if test` seem to be interspersed with `[` and `test` with no apparent rhyme or reason. `test` shows up on occasion, like at [config.site for vendor libs on Fedora x86_64.
@Calmarius If you're used to C, think of `return` statuses, not booleans, where `return 0` means success.