I'm using getopts
and case...esac
for the first time. I've seen tutorials and questions with many different patterns for the default/catch-all option: ?
, *
, \?
, [?]
. They all seem to function the same, as you can see if you change their order in this script:
#!/bin/bash
set -e
set -u
set -o pipefail
while getopts ":d:l:h:" opt; do
case $opt in
d) echo getopts saw $opt with value $OPTARG ;;
l) echo getopts saw $opt with value $OPTARG ;;
h) echo getopts saw $opt with value $OPTARG ;;
:) echo "getopts saw $opt with value $OPTARG and went to :" ;;
*) echo "getopts saw $opt with value $OPTARG and went to *" ;;
?) echo "getopts saw $opt with value $OPTARG and went to ?" ;;
\?) echo "getopts saw $opt with value $OPTARG and went to \?" ;;
[?]) echo "getopts saw $opt with value $OPTARG and went to [?]" ;;
esac
done
echo script done
Running the code below will always stop at the first matching option in the case
list:
$ ./test.sh -c
getopts saw ? with value c and went to *
script done
Are all of these exactly the same?
In response to @BenjaminW.'s comment:
The manual quote below explains that getopts
will return ?
vs :
depending on whether getopts
is set to silent. So my modified questions are:
- Are
?
,\?
, and[?]
equivalent? - Is the
*
unnecessary?
From the manual: If a required argument is not found, and getopts is not silent, a question mark (‘?’) is placed in name, OPTARG is unset, and a diagnostic message is printed. If getopts is silent, then a colon (‘:’) is placed in name and OPTARG is set to the option character found.