Posts Tagged ‘ zsh

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.

It turns out that the advanced bash scripting guide does talk about this! Casually, and without any kind of callout. On page 203. As part of the discussion of internal commands.

It turns out that what I wanted was to use the standard getopts loop, followed by a call to shift:

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

You see, 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.

Technorati Tags: , ,