Optional option argument with getopts
Wrong. Actually getopts
does support optional arguments! From the bash man page:
If a required argument is not found, and getopts is not silent, a question mark (?) is placed in name, OPTARG is unset, and a diagnosticmessage is printed. If getopts is silent, then a colon (:) is placed in name and OPTARG is set to the option character found.
When the man page says "silent" it means silent error reporting. To enable it, the first character of optstring needs to be a colon:
while getopts ":hd:R:" arg; do # ...rest of iverson's loop should work as posted done
Since Bash's getopt does not recognize --
to end the options list, it may not work when -R
is the last option, followed by some path argument.
P.S.: Traditionally, getopt.c uses two colons (::
) to specify an optional argument. However, the version used by Bash doesn't.
getopts
doesn't really support this; but it's not hard to write your own replacement.
while true; do case $1 in -R) level=1 shift case $1 in *[!0-9]* | "") ;; *) level=$1; shift ;; esac ;; # ... Other options ... -*) echo "$0: Unrecognized option $1" >&2 exit 2;; *) break ;; esacdone
This workaround defines 'R' with no argument (no ':'), tests for any argument after the '-R' (manage last option on the command line) and tests if an existing argument starts with a dash.
# No : after Rwhile getopts "hd:R" arg; do case $arg in (...) R) # Check next positional parameter eval nextopt=\${$OPTIND} # existing or starting with dash? if [[ -n $nextopt && $nextopt != -* ]] ; then OPTIND=$((OPTIND + 1)) level=$nextopt else level=1 fi ;; (...) esacdone