2

I want to create a bash script which will have lot of options while executing.

# script.sh  --dry-run --user <parameter1> --pass <parameter2>

I heard about getopt option but looks like we can only write either --user or --password or --dry-run and not all of them. Basically I want to take --user parameter1 as input1 and --pass parameter2 as input2 and a special case where if --dry-run option is there, then execute only dry-run code instead of production.

#!/bin/bash
user=$1
pass=$2

help() {
    cat<<EOF
Usage : $0 --dry-run --user <user_id> --pass <password>
you can specify --dry-run or --production
EOF
}

[ ${3} ] || help

function dry_run() {
    // --dry-run code 
}

function production() {
   // --production code 
}

I want to validate --dry-run and if the option is --dry-run, then execute function dry_run() else execute production() function. But how to write options and validations ?

2
  • Take a look at shellcheck.net
    – Cyrus
    Mar 14, 2015 at 15:41
  • Sure you can specify multiple long options. It is just how you process them if specifying multiple make sense or not.
    – Anthon
    Mar 14, 2015 at 16:25

2 Answers 2

2

If I've understood what you're after, you can do it with getopt:

#!/bin/bash

PARAMS=$(getopt -l dry-run,production,user:,pass: -n $0 "" -- "$@")
if [ $? != 0 ]; then exit 1; fi
eval set -- "$PARAMS"

dryrun=false

while [ -n "$1" ]; do
    case "$1" in
        --dry-run) dryrun=true; shift;;
        --production) dryrun=false; shift;;
        --user) user="$2"; shift 2;;
        --pass) pass="$2"; shift 2;;
        --) shift;;
        *) exit 1;;
    esac
done

if [ $dryrun = true ]; then
    ...
else
    ...
fi

You can add more processing if you want to forbid specifying both --dry-run and --production, or if --user and --password are required.

0
0

You don't really need getopt to handle script long-options. The getopts builtin function can do it as well (and usually without subshells). The trick is to use - as an option. That way --dry-run (for example) becomes optvar=- and OPTARG=-dry-run. Here's a functional example of how you might do it specifically for this case:

#!/bin/sh
help(){ echo usage; }                       #dummy help
unset   user dryrun pass _o o               #ensure all flag vars are unset
while   getopts :-:u:p:d o              &&  #getopts loop
        o=${o#-}        _o=${o:+$OPTARG}    #empty $o if $o==-
do      case            $o$OPTARG       in  #test concatenated $o$OPTARG
        (u*|-user)      user=${_o:-$2}  ;;  #set $user to $_o or $2
        (p*|-pass)      pass=${_o:-$2}  ;;  #ditto for $pass
        (d*|-dryrun)    o=d dryrun=1    ;;  #no $OPTARG either way - o=d base
        (*)             !  help         ;;  #no usage options met - opt error
        esac || exit                        #quit with error if opt == ! help
        shift "$((!${#o}+(OPTIND-(OPTIND=1))))"  #shift params as they're read
done

This will run as is. In fact I tried several different option possibilities with it. For example:

~/getopts.sh -p-user --user me -uyou -d --dry-run

...when run w/ a #!/bin/sh -x bangline printed this to my stderr:

+ unset user dryrun pass _o o
+ getopts :-:u:p:d o
+ o=p _o=-user
+ pass=-user
+ shift 1
+ getopts :-:u:p:d o
+ o= _o=
+ user=me
+ shift 2
+ getopts :-:u:p:d o
+ o=u _o=you
+ user=you
+ shift 1
+ getopts :-:u:p:d o
+ o=d _o=
+ o=d dryrun=1
+ shift 1
+ getopts :-:u:p:d o
+ o= _o=
+ o=d dryrun=1
+ shift 1
+ getopts :-:u:p:d o

After completing the getopts loop you can just do...

[ "$((dryrun))" -eq 0 ] && production || dryrun

...if you have declared the production() and dryrun() functions. They'll find any command-line values specified for $pass and/or $user assigned as necessary. If either of those has not been declared on the command-line, you might consider referencing them like:

echo "${user=default_username}" "${pass=default_password}"

...just to cover all of your bases.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .