A && B || C
is not if-then-else. C may run
when A is true.[[ $dryrun ]] && echo "Would delete file" || rm file
if [[ $dryrun ]]
then
echo "Would delete file"
else
rm file
fi
It's common to use A && B
to run B
when A
is true, and A || C
to run
C
when A
is false.
However, combining them into A && B || C
is not
the same as if A then B else C
.
In this case, if A
is true but B
is false,
C
will run.
For the code sample above, if the script was run with stdout closed
for any reason (such as explicitly running
script --dryrun >&-
), echo would fail and the file
would be deleted, even though $dryrun
was set!
If an if
clause is used instead, this problem is
avoided.
We can think of the example above as
((([[ $dryrun ]]) && echo "Would delete file") || rm file)
expressing the left-associativity of the &&
||
operators.
Whenever a command (strictly, a pipeline) succeeds or fails, the
execution proceeds following the next &&
(for
success) or ||
(for failure). (More strictly, the
parentheses should be replaced with { command; }
to avoid
making a subshell, but that's ugly and boring.)
Ignore this warning when you actually do intend to run C when either A or B fails.
ShellCheck is a static analysis tool for shell scripts. This page is part of its documentation.