Using getopts inside a Bash function
As @Ansgar points out, the argument to your option is stored in ${OPTARG}
, but this is not the only thing to watch out for when using getopts
inside a function. You also need to make sure that ${OPTIND}
is local to the function by either unsetting it or declaring it local
, otherwise you will encounter unexpected behaviour when invoking the function multiple times.
t.sh
:
#!/bin/bashfoo(){ foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; } local OPTIND o a while getopts ":a:" o; do case "${o}" in a) a="${OPTARG}" ;; *) foo_usage ;; esac done shift $((OPTIND-1)) echo "a: [${a}], non-option arguments: $*"}foofoo -a bc bar quuxfoo -x
Example run:
$ ./t.sha: [], non-option arguments:a: [bc], non-option arguments: bar quuxfoo: [-a <arg>]
If you comment out # local OPTIND
, this is what you get instead:
$ ./t.sha: [], non-option arguments:a: [bc], non-option arguments: bar quuxa: [bc], non-option arguments:
Other than that, its usage is the same as when used outside of a function.
Here is simple example of getopts
usage within shell function:
#!/usr/bin/env basht() { local OPTIND getopts "a:" OPTION echo Input: $*, OPTION: $OPTION, OPTARG: $OPTARG}t "$@"t -a foo
Output:
$ ./test.sh -a bcInput: -a bc, OPTION: a, OPTARG: bcInput: -a foo, OPTION: a, OPTARG: foo
As @Adrian pointed out, local OPTIND
(or OPTIND=1
) needs to be set as shell does not reset OPTIND
automatically between multiple calls to getopts
(man bash
).
The base-syntax for getopts
is:
getopts OPTSTRING VARNAME [ARGS...]
and by default, not specifying arguments is equivalent to explicitly calling it with "$@" which is: getopts "a:" opts "$@"
.
In case of problems, these are the used variables for getopts
to check:
OPTIND
- the index to the next argument to be processed,OPTARG
- variable is set to any argument for an option found bygetopts
,OPTERR
(not POSIX) - set to 0 or 1 to indicate if Bash should display error messages generated by thegetopts
.
Further more, see: Small getopts tutorial at The Bash Hackers Wiki