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.