Let's say I'm running getopts
in a Bash script with the option string ":a:b" and I provide the following command line parameters:
./script.sh -a foo bar -b bar zappo
The instance of "foo" is an expected argument for the option a
and the option b
has no expected argument. However, both instances of "bar" and the instance of "zappo" are unacceptable to getopts
. After running getopts
, how can I echo a variable containing a list of all of the unacceptable arguments? How could I produce the list "bar bar zappo"? Thanks!
Here's some code for your convenience:
#!/bin.bash
option_string=":a:b"
unexpected_parameters=""
OPTIND=1
while getopts "${option_string}" options; do
case ${options} in
a)
echo "-a triggered with parameter ${OPTARG}" >&2 # output to STDERR
;;
b)
echo "-b triggered" >&2 # output to STDERR
;;
\?)
echo "invalid option: -${OPTARG}" >&2 # output to STDERR
;;
esac
#<insert code magic... unexpected_parameters="${unexpected_parameters} "$(MAGIC)"">
done
echo "unexpected parameters: ${unexpected_parameters}"
getopts
stops processing at the first non-option argument. That's Posix-style argument processing. In Posix-style argument processing, given the commandutility
will not interpret-b
as a command-line flag. If-a
takes an argument, thenbar
will be the first positional argument, and then there will be three more positional arguments,-b
,bar
, andzappo
.GNU extends this syntax by permuting command-line arguments so that flag options can be anywhere in the command-line. However, if you set the environment variable
POSIXLY_CORRECT
, then GNU utilities will (mostly) behave like normal Posix utilities. The GNU version of the Posix C library functiongetopt(3)
(andgetopt_long(3)
) use GNU syntax by default, and also react appropriate to thePOSIXLY_CORRECT
environment variable.However, the bash
getopts
builtin is strictly Posix-style. So in your case, withgetopts ":a:b"
, your loop will only be executed once, for flaga
with argumentfoo
. Whengetopts
terminates,OPTIND
is set the the index of the first unconsumed command-line argument, in this case3
(bar
).If you want to use
getopts
with GNU-style option handling, you have to do the permuting yourself. For example, you could do something like this:Alternatively, you can use the GNU implementation of
getopt(1)
, which will do all that for you, at the cost of a slightly more annoying interface. (At least, I find it annoying, but YMMV.)