dannyman.toldme.com

About Me : Free Style : Good Reads : News and Reaction : Photographs : Technical : Travels : Unsorted

Search:
June 22, 2005
Technical

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 start
./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 shift.

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"

Notes:

Read More

Next: Quizzes are Dumb
Previous: Evolve!
Categories: Technical
Possibly-Related Posts
sh: “split” Shortcut
HOWTO: Random Number in Shell Script
Shell HOWTO: Remove Duplicate Elements from a Variable
Mac OS X and per-user Support for .htaccess
Shaddup, Firefox!
Perl: Convert Celsius and Fahrenheit
FreeBSD HOWTO: Software Mirror System Disk

Responses

June 22nd, 2005

Andrew Ho

My standard sh command line parsing loop looks like this:

    while [ $# != 0 ]; do
        flag="$1"
        case "$flag" in
            -a) echo "You provided the -a flag, which takes no arguments"
                ;;
            -b) if [ $# -gt 1 ]; then
                    arg="$2"
                    shift
                else
                    echo "You did not provide an argument for the -b flag"
                fi
                echo "You supplied an argument for the -b flag: $arg"
                ;;
             *) echo "Unrecognized flag or argument: $flag"
                ;;
        esac
        shift
    done

If you are using bash instead of sh, you can accept both -fvalue and -f value variants:

           -b*) arg="${arg##-b}"
                echo "You attached an argument to the -b flag: $arg"
                ;;

My code doesn’t reset $@. I have a README file in my homedir that reminds me of the other neat bash-ism that I like to use: ${1+"$@"} expands to $@, but if $@ is empty, it expands to an empty list (different from “$@” which would expand to the single empty string “”).

June 24th, 2005

an_agent

FAI…

shift $((OPTIND - 1))

works in bash (not sh) without having to pipe to bc.

January 15th, 2008

Ted Henry

Thanks for this post! This is exactly what I needed :-)

Post a Public Comment

The Rules:

  1. For private messages, e-mail me: dannyman@toldme.com
  2. I will not publish or share your e-mail address.
  3. I will not spam you.
  4. Therefor: no anonymous posts; send me your e-mail address!
(required)
(required)

. . . comments from new posters will be held for screening.

Danny Howard is 100% responsible for the content on this site, except some of it is stolen.

All rights are reserved, unless otherwise noted. Generally, I'm a BSD guy, so you can assume implicit permission to adapt, modify, and redistribute my intellectual property with appropriate attribution. Except some of this content is itself re-appropriated, so you'd best ask first, especially for commercial use. Thanks!

You can contact me via e-mail: dannyman@toldme.com

Most of http://dannyman.toldme.com/ is powered by WordPress.

If you're hip to RSS and whatnot, you can subscribe to this site.

These links are for dannyman: login AND backlinks