Is there a reason to use “[ ! -f file ] || command” instead of “[ -f file ] && command”?

I found

[ ! -f /etc/default/lxc-net ] || . /etc/default/lxc-net

in /etc/default/lxc on Ubuntu 16.04 which seems to be replacing (my own or package maintainer code)

[ -f /etc/default/lxc-net ] && . /etc/default/lxc-net

Since the test is counter-intuitive (in case of failure of the test about non-presence of the file run the command) I was wondering if it has any advantage over the &&-version.

Answer

Yes, if you care about the exit code of the compound statement. Try the following:

#/bin/sh

! $1 || true
echo $?

$1 && true
echo $?

then run it with true and false as arguments.

./script true
0
0

./script false
0
1

This is because short-circuit evaluation of boolean expressions.

In OP’s example, let’s suppose the file doesn’t exist:

  • In the first case, the first condition returns TRUE, no need to evaluate the second operation (TRUE OR x = TRUE). You get a TRUE for the compound statement.
  • In the second case, the first condition returns FALSE, no need to evaluate the second operation (FALSE AND x = FALSE). You get a FALSE for the compound statement.

Exit codes are very important. Check this SO answer to see possible implications of set -e, trap and set -o pipefail.

Leave a Reply

Your email address will not be published. Required fields are marked *