How to use getopts option without argument at the end in bash

Nissim picture Nissim · Dec 27, 2015 · Viewed 11.4k times · Source

I want to use getopts in bash. The user should select his own options. most of the options gets arguments but there are 2 options that does not gets an argument. It works good when the option without the argument is at the middle of the command, but when it is at the end it does not work.

Note - the first two arguments (Server and Password) are mandatory and not a part of the getopts.

#!/bin/bash

SERVER=${1}
PASSWORD=${2}
VERSION=v0
ASKED_REVISION=0
DB=schema_1
PROPERTIES=1
FULL=0
USER=

# Usage info
show_help()
{
echo "
        Usage: Environment DBPassword [-V Version] [-R Revision] [-S Schema] [-P] [-F] [-U Username]

        -V Version      Version to deploy.
        -R Revision     Revision number (0 means the latest revision).
        -S Schema       Schema in the DB to deploy.
        -P              No(!) External Properties. If this flag is marked the deploy will not copy the external properties
        -F              Full deploy
        -U              Username. This User who run the deploy.

        For Example: ./deploy server1 123456 -V v1.0 -R 12345 -S schema1 -P -F -U User1

        -H              Help
"
}
OPTIND=3
while getopts ":V:R:S:P:F:U:H:" FLAG; do
  case "$FLAG" in
        V) # Set option "V" [Version]
                VERSION=$OPTARG
                ;;
        R) # Set option "R" [Revision]
                ASKED_REVISION=$OPTARG
                ;;
        S) # Set option "S" [Schema]
                DB=$OPTARG
                ;;
        P) # Set option "P" [No External Properties]
                PROPERTIES=0
                OPTIND=$OPTIND-1
                ;;
        F) # Set option "F" [FULL]
                FULL=1
                OPTIND=$OPTIND-1
                ;;


 U) # Set option "U" [User]
            USER=$OPTARG
            ;;
    H) # help
            show_help
            ;;
    \?)
            echo "Invalid option: -$OPTARG. Use -H flag for help."
            exit
            ;;
  esac
done

shift $((OPTIND-1))  #This tells getopts to move on to the next argument.

echo "Env=$SERVER"
echo "Pass=$PASSWORD"
echo "Version=$VERSION"
echo "Revision=$ASKED_REVISION"
echo "Schema=$DB"
echo "External Properties=$PROPERTIES"
echo "FULL=$FULL"
echo "USER=$USER"

-F and -P shouldn't get an argument. When I run this command it works correctly (-F in the middle):

./deploy_test.sh server1 pass1234 -U 555 -R 55555 -F -V v1.0

When the -F or -P are in the end of the command, This line is not working correctly (everything works good but the -F):

./deploy_test.sh server1 pass1234 -U 555 -R 55555 -V v1.0 -F

Answer

Julian picture Julian · Dec 27, 2015

Remove the colons from the options that don't require arguments, and don't manually do any shifting or changing of OPTIND yourself within the while / case statment (you'll still need to set OPTIND prior to the while loop to skip the first 2 arguments):

while getopts ":V:R:S:PFU:H" FLAG; do

I've shown the while line with the appropriate changes for the P and F options as well as for H since it also wouldn't require an argument.

As per the documentation:

if a character is followed by a colon, the option is expected to have an argument

So the : should only be there for options with arguments.