Why doesn't using multiple commands with a || or && conditional work?
Note that your line
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
this is the same as
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."
exit 1
(an unquoted ;
can, in most circumstances, be replaced by a newline character)
This means that the exit 1
statement is always executed regardless of how many arguments were passed to the script. This in turn means that the message The given argument is empty.
would never have a chance of getting printed.
To execute more than a single statement after a test using the "short-circuit syntax", group the statements in { ...; }
. The alternative is to use a proper if
statement (which, IMHO, looks cleaner in a script):
if [ "$#" -ne 1 ]; then
echo 'Invalid number of arguments, expected one.' >&2
exit 1
fi
You have the same issue with your second test.
Regarding
[ -z "" ] && echo A || echo B
This would work for the given example, but the generic
some-test && command1 || command2
would not be the same as
if some-test; then
command1
else
command2
fi
Instead, it is more like
if ! { some-test && command1; }; then
command2
fi
or
if some-test && command1; then
:
else
command2
fi
That is, if either the test or the first command fails, the second command executes, which means it has the potential to execute all three involved statements.
This:
[ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; exit 1
is not:
[ "${#}" -eq 1 ] || { echo "Invalid number of arguments, expected one."; exit 1; }
But instead is:
{ [ "${#}" -eq 1 ] || echo "Invalid number of arguments, expected one."; }
exit 1
Your script is exiting regardless of how many arguments you passed to it.
One way to make it more readable is to define a die
function (à la perl
) like:
die() {
printf >&2 '%s\n' "$@"
exit 1
}
# then:
[ "$#" -eq 1 ] || die "Expected one argument, got $#"
[ -n "$1" ] || die "Empty argument not supported"
You can add more bells and whistles like colours, prefix, line number... if need be.