Consider adding a default *)
case, even if it just exits with error.
Problematic code:
case "$1" in
start) start_service ;;
stop) stop_service ;;
restart|reload|force-reload)
stop_service;
start_service;;
esac
Correct code:
case "$1" in
start) start_service ;;
stop) stop_service ;;
restart|reload|force-reload)
stop_service;
start_service;;
*)
echo >&2 "Invalid choice: $1"
exit 1
esac
Rationale:
ShellCheck found a case
statement that may not be considering all possible cases. This may mean that only the happy paths are accounted for.
Consider adding a default case to handle other values. If you don't know what to do or don't believe it'll ever happen, exiting with an error is good, fail-fast practice.
The example is adapted from a real world Debian init script, which due to a missing default case reports success on any misspelled command (here with underscore instead of dash):
$ /etc/init.d/screen-cleanup force_reload && echo success
success
Exceptions:
This suggestion only triggers in verbose mode (-S verbose
).
If you don't have a default case because the default should be to take no action, consider adding a comment to other humans:
case "$(uname)" in
CYGWIN*) cygwin=1;;
MINGW*) mingw=1;;
*) ;; # No special workarounds identified
esac
If you believe that it's impossible for the expression to have any other value, it's considered good practice to add the equivalent of an assert(0)
to fail fast if this assumption should turn out to be incorrect in the current or future versions:
case "$result" in
true) proceed;;
false) cancel;;
*) echo >&2 "Submit bug report: '$result' should be true or false."
exit 127
esac
Related resources:
- Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc!