Search code examples
bashgetopts

Why would a script have multiple questions marks in the OptionString of getopts


I have a script that has the following line:

while getopts "b:?1:?2:?g:r:n:t:?o:?" opt; do

how is this any different than:

while getopts "b:1:2:g:r:n:t:o:" opt; do


Solution

  • how is this any different than:

    The first one is invalid. It's as different, as ? will be most probably ignored by most getopts implementations, but if getopts decided to error on invalid optstring that would be fine. From posix getopts:

    optstring

    A string containing the option characters recognized by the utility invoking getopts. [...]

    The characters <question-mark> and <colon> shall not be used as option characters by an application. [...]

    There are no other mentions of ?, except for error handling. getopt is a really simple utility, the ? is returned by getopt in case of parsing error.

    The author most probably meant to do "optional option argument" - getopt does not support such functionality (and if it would, I believe it would be denoted by two :: like in GNU getopt).

    Looking at bash sources getopt.c, bash uses simple strchr to scan for the option in optstring. Because there's ?, it is interpreted as an option - it becomes impossible (or unnecessary hard) to differentiate between error and success, as ? is returned in case of error.

    $ OPTIND=0; set -- -'?' -g; while getopts "something:?does_not_matter" opt; do echo "$opt" "$OPTARG"; done
    ?                                              # This is valid -? option
    bash: option requires an argument -- g
    ?                                              # This is error
    
    $ OPTIND=0; set -- -'?'; while getopts "something:does_not_matter" opt; do echo "$opt" "$OPTARG"; done
    bash: illegal option -- ?
    ?                                              # This is error