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.


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

[ ${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 ?

  • Take a look at shellcheck.net – Cyrus Mar 14 '15 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 '15 at 16:25

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


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


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;;

if [ $dryrun = true ]; then

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

| improve this answer | |

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:

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

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.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.