Though I can't reproduce the initial run of the function that you have in your question, you should reset OPTIND
to 1 in your function to be able to process the function's command line in repeated invocations of it.
From the bash
manual:
OPTIND
is initialized to 1 each time the shell or a shell script is invoked. When an option requires an argument, getopts
places that argument into the variable OPTARG
. The shell does not reset OPTIND
automatically; it must be manually reset between multiple calls to getopts
within the same shell invocation if a new set of parameters is to be used.
From the POSIX standard:
If the application sets OPTIND
to the value 1, a new set of parameters can be used: either the current positional parameters or new arg values. Any other attempt to invoke getopts
multiple times in a single shell execution environment with parameters (positional parameters or arg operands) that are not the same in all invocations, or with an OPTIND
value modified to be a value other than 1, produces unspecified results.
The "shell invocation" that the bash
manual mentions is the same as the "single execution environment" that the POSIX text mentions, and both refer to your shell script or interactive shell. Within the script or interactive shell, multiple calls to your lscf
will invoke getopts
in the same environment, and OPTIND
will need to be reset to 1 before each such invocation.
Therefore:
lscf() { OPTIND=1 while getopts f:d: opt ; do case $opt in f) file="$OPTARG" ;; d) days="$OPTARG" ;; esac done echo file is $file echo days is $days }
If the variables file
and days
should not be set in the calling shell's environment, they should be local variables. Also, quote variable expansions and use printf
to output variable data:
lscf() { local file local days OPTIND=1 while getopts f:d: opt ; do case $opt in f) file="$OPTARG" ;; d) days="$OPTARG" ;; esac done printf 'file is %s\n' "$file" printf 'days is %s\n' "$days" }
local OPTIND
at the first of your function