The only way your case
statement isn't going to match with no $1
given is if it isn't entered in the first place.
Consider the following:
#!/usr/bin/env bash
set -e
command=$1
shift
case $command in
*) echo "Default case was entered";;
esac
This emits no output when $1
is unset -- but not because anything wrong with the case
statement.
Rather, the issue is that shift
exits with a nonzero exit status when there's nothing available to shift, and the set -e
causes the script as a whole to exit on that failure.
First Moral Of This Story: Don't Use set -e
(or #!/bin/bash -e
)
See BashFAQ #105 for an extended discussion -- or the exercises included therein if in a hurry. set -e
is wildly incompatible between different "POSIX-compliant" shells, and thus makes behavior hard to predict. Manual error handling may not be fun, but it's much more reliable.
Second: Consider A Usage Function
This gives you a terse way to have your usage message in one place, and re-use it where necessary (for example, if you don't have a $1
to shift
):
#!/usr/bin/env bash
usage() { echo "Usage: $0 {loop|...}" >&2; exit 1; }
command=$1
shift || usage
case $command in
*) usage ;;
esac
Because of the || usage
, the exit status of shift
is considered "checked", so even if you do run your script with set -e
, it will no longer constitute a fatal error.
Alternately, Mark The shift
As Checked Explicitly
Similarly:
shift ||:
...will run shift
, but then fall back to running :
(a synonym for true
, which historically/conventionally implies placeholder use) should shift
fail, similarly preventing set -e
from triggering.
Aside: Use Lower-Case Names For Your Own Variables
POSIX specifies that the shell (and other tools to which the standards applies) have their behavior modified only by environment variables with all-caps names:
Environment variable names used by the utilities in the Shell and Utilities volume of POSIX.1-2017 consist solely of uppercase letters, digits, and the ( '_' ) from the characters defined in Portable Character Set and do not begin with a digit. Other characters may be permitted by an implementation; applications shall tolerate the presence of such names. Uppercase and lowercase letters shall retain their unique identities and shall not be folded together. The name space of environment variable names containing lowercase letters is reserved for applications. Applications can define any environment variables with names from this name space without modifying the behavior of the standard utilities.
This applies even to regular, non-export
ed shell variables because specifying a shell variable with the same name as an environment variable overwrites the latter.
BASH_COMMAND
, for example, has a distinct meaning in bash -- and thus can be set to a non-empty value at the front of your script. There's nothing stopping COMMAND
from similarly being meaningful to, and already used by, a POSIX-compliant shell interpreter.
If you want to avoid side effects from cases where your shell has set a built-in variable with a name your script uses, or where your script accidentally overwrites a variable meaningful to the shell, stick to lowercase or mixed-case names when writing scripts for POSIX-compliant shells.