Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

OPTIND set incorrectly by getopts for options without arg



Back in 2007 there was a question posted to the mailing list regarding
OPTIND and getopts (http://www.zsh.org/mla/users/2007/msg01188.html). To
quote, with some notes and one modifcation:

With zsh 4.3.4 the OPTIND incremental bebavior is inconsistent for options
with argument and without argument. For option with argument, OPTIND points
to next argument, while for option without argument it points to current
argument.

func() {
  OPTIND=1        # reset OPTIND each time in to prevent carryover
  getopts a:b optvar
  shift $(( OPTIND -1 ))
  echo "$OPTIND, $1"
}

func -a x y z
output: 3, y      # this is the correct output

func -b x y z
output: 1, -b     # this is the questionable output

Is this a bug? There is no consistent way to do "shift" as such.


Turns out according to the POSIX spec this is a bug (
http://pubs.opengroup.org/onlinepubs/000095399/utilities/getopts.html)

When the end of options is encountered, the getopts utility shall exit with
a return value greater than zero; the shell
variable OPTIND shall be set to the index of the first
non-option-argument.... Any of the following shall identify the end of
options: the special option "--", finding an argument that does not begin
with a '-', or encountering an error.


Unless I'm misreading that means that in the first example "y" indicates
the end of options so the correct output is "3, y".  In the second example
the "x" indicates the end of options so the correct output is "2, x".  For
what it's worth bash and dash set OPTIND in this way.

The original email was regarding zsh 4.3.4.  I can confirm this is still
the behavior at zsh 4.3.9.

Simon


Messages sorted by: Reverse Date, Date, Thread, Author