Using getopts with required args in a posix shell
I recently wanted to add a verbose flag to a script. My script required some arguments, and I didn’t want to change the (very limited) already existing logic. Because programming in bash sucks enough that I am willing to spend 6 hours googling “getopts options with args” rather than re-arrange 3 lines of code.
This seems like such a common need that I figured it would be easily googlable, but based on the number of unanswered forum posts that I found, it isn’t.
OPTIND=1 while getopts "k:vh" o ; do # set $o to the next passed option case "$o" in v) # set "v" flag ;; k) # do something with "k" and $OPTARG, the arg to this opt ;; h) print "$usage" exit ;; esac done shift $(($OPTIND - 1)) # $1 is now the first non-option argument, $2 the second, etc
getopts sets the
$OPTIND POSIX variable to the index of the option that it should process next every time it’s called, and
shift arg shifts arg arguments off the argument list.
Combining those two facts, and using the
$(( )) numeric context, lets you set a bunch of options and then act as though your script has only arguments in any POSIX-compliant shell.
I think. This is working for me in bash and zsh, and it’s part of the POSIX standard, so it should be true for you.