Pattern: Use of function as condition with set -e
Issue: -
Function is used as a condition in a script where set -e
is enabled. This means that the function will run without set -e
, and will power through any errors.
This applies to if
, while
, and until
statements, commands negated with !
, as well as the left-hand side of ||
and &&
. It does not matter how deeply the command is nested in such a structure.
In the problematic example, the intent was that an error like cp: error writing '/backup/important.txt': No space left on device
would cause the script to abort. Instead, since the function is invoked in an if
statement, the script will proceed to delete all the files even though it failed to back them up.
The fix is to call it outside of an if
statement. There is no point in checking whether the command succeeded, since the script would abort if it didn't. You may also want to consider replacing set -e
with explicit || exit
after every relevant command to avoid such surprises.
Example of incorrect code:
#!/bin/sh
#shellcheck enable=check-set-e-suppressed
set -e
backup() {
cp *.txt /backup
rm *.txt # Runs even if copy fails!
}
if backup
then
echo "Backup successful"
fi
Example of correct code:
#!/bin/sh
#shellcheck enable=check-set-e-suppressed
set -e
backup() {
cp *.txt /backup
rm *.txt
}
backup
echo "Backup successful"