Why not use && as a shortcut in shell scripting

Date: — Topic: — Lang: — by Slatian

Ever seen some shell code that seems double negated, here is why.

Table of Contents

What am I Talking About

If you've been shell scripting for some time you have most probably seen the following construct:

[ -n "$something" ] && foo

This runs the foo command, but only if $something isn't empty, a very useful and common thing to check for in some scripts. So far no problem.

Another useful thing in scripts is set -e which aborts the whole script if some "line" (as in collection of commands) returns with a non-zero exit code. It makes sure that a shell script exits instead of causing havoc.

The problem now arises when one combines the two.

Now if $something isn't empty everything works fines as before, but if it is empty, the test returns an error code, which gets treated as a signal to stop the script. Not good.

How to Fix it the Verbose Way

One place a command is allowed to fail is inside the condition of an if statement, pretty obvious when one says it out loud, because that is literally the job of the if, redirect the flow of execution based on whether a command was successful or not.

So the above can be rewritten to:

set -e
#

if [ -n "$something" ] ; then
	foo
fi

Which works as intended again, but is kind of bulky.

The Working Shortcut

A way of using a shortcut with set -e is rephrasing the problem so that the test returning false gets caught.

For this to happen one has to invert the condition and catch when it fails, luckily most commands used in such shortcut condition usually also support testing for the opposite.

Manual for test and [

So that the initial construct can be rewritten as:

[ -z "$something" ] || foo

The -z tests is a string is empty, so the exact opposite of -n, if the test for emptiness fails the command gets run.

An easier way to read this is:

Either $something is empty (happy) or we run foo (also happy)

That's it!

This of course depends on foo succeeding, which I assumed the whole time for readability. If your shellscript also makes that assumption it is usually a very good idea to use set -e.

Also this doesn't affect what you use inside the condition of an if statement, there && is completely fine.

A happy Slatian notes:

Thanks for reading! I know it has been a while.

If you want to learn more, see my other shell articles.