Argument Parsing in Shell Scripts
So, say you are writing a shell script (sh or bash) that needs to take arguments like so:
./script.sh -v start
./script.sh -c foo.conf start
./script.sh -vc foo.conf start
This took me a bit of doing. First, I tried
getopt but apparently all that does is disambiguate -v from -c. That, and the FreeBSD man page claims to have improved the example by making it completely inscrutable.
Eventually I found a reference that explained how to use
getopts, which worked a lot better, but all the examples I could find didn’t tell you how to reset
Eventually, I figured out that that last bit is accomplished with
Here’s example code:
#!/bin/sh # conf=default.conf while getopts c:hv o do case "$o" in c) conf="$OPTARG";; h) echo "Usage: $0 -hv -c <config> [start|stop|restart|status]" && exit 1;; v) verbose="yes";; \?) echo "Usage: $0 -hv -c <config> [start|stop|restart|status]" && exit 1;; esac done # Reset $@ shift `echo $OPTIND-1 | bc` echo "conf: $conf" echo "command: $1"
- The while loop iterates
$@where it conforms to the getopts configuration.
- getopts c:hv indicates that -h and -v are boolean arguments, and -c is followed by a string argument.
- $OPTIND is set at the end of getopt, and indicates how many arguments through $@ it parsed.
- Oh, and the shift operation resets
$@by $OPTIND-1, so that
$1ends up pointing at the start command, or whatever.
- If you’re programming in ksh, you can just set
$OPTIND-1. But if you’re programming in ksh you are far beyond needing to check my blog for argument parsing.