[SOLVED] Parse for command line options using enhanced getopt

All Gurus once were Newbies
Forum rules
There are no such things as "stupid" questions. However if you think your question is a bit stupid, then this is the right place for you to post it. Please stick to easy to-the-point questions that you feel people can answer fast. For long and complicated questions prefer the other forums within the support section.
Before you post please read how to get help
Post Reply
kwyrky
Level 2
Level 2
Posts: 57
Joined: Wed Jul 10, 2019 5:10 am

[SOLVED] Parse for command line options using enhanced getopt

Post by kwyrky » Sun Aug 18, 2019 4:01 am

I found a nice example script here which is a little demo on how to parse for command line options (on this page search for the answer which has "enhanced getopt" in it by Robert Siemer): https://stackoverflow.com/questions/192 ... ts-in-bash

I tried to modify it for my needs so instead of one I have two parameters which take an option...

Code: Select all

#!/bin/bash

############################################################################################################
#COMMAND LINE OPTIONS
############################################################################################################

# saner programming env: these switches turn some bugs into errors
set -o errexit -o pipefail -o noclobber -o nounset

# -allow a command to fail with !’s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! getopt --test > /dev/null 
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
    echo 'I’m sorry, `getopt --test` failed in this environment.'
    exit 1
fi

OPTIONS=dfku:v
LONGOPTS=debug,force,keyfile,uuid:,verbose

# -regarding ! and PIPESTATUS see above
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via   -- "$@"   to separate them correctly
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
    # e.g. return value is 1
    #  then getopt has complained about wrong arguments to stdout
    exit 2
fi
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"

# set defaults
d=n 
f=n 
v=n 
keyfile=
uuid=

# now enjoy the options in order and nicely split until we see --
while true; do
    case "$1" in
        -d|--debug)
            d=y
            shift
            ;;
        -f|--force)
            f=y
            shift
            ;;
        -v|--verbose)
            v=y
            shift
            ;;
        -k|--keyfile)
            keyfile="$2"
            shift 2
            ;;
        -u|--uuid)
            uuid="$2"
            shift 2
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "Programming error"
            exit 3
            ;;
    esac
done

echo "verbose: $v, force: $f, debug: $d, keyfile: $keyfile, uuid: $uuid" 
if I run the script with

Code: Select all

./script -d -f -v -u myuuid
it works and I get

Code: Select all

verbose: y, force: y, debug: y, keyfile: , uuid: myuuid
but if I run it with setting parameter k like

Code: Select all

./script -d -f -v -k mykeyfile -u myuuid
or

Code: Select all

./script -d -f -v -k mykeyfile
it prints out

Code: Select all

Programming error
so the last case is executed...

So why is that? How can I fix this?

kwyrky
Level 2
Level 2
Posts: 57
Joined: Wed Jul 10, 2019 5:10 am

Re: [SOLVED] Parse for command line options using enhanced getopt

Post by kwyrky » Sun Aug 18, 2019 6:18 am

Ok after reading about getopt I found out I had to put another double colon ":" next to the parameter k / keyfile because this tells getopt that this parameter requires an argument, which is true in this case. It should look like this:

Code: Select all

...
OPTIONS=dfk:u:v
LONGOPTS=debug,force,keyfile:,uuid:,verbose
...

Post Reply

Return to “Newbie Questions”