Command line arguments validation with GetOpts and mandatory parameters

donhector picture donhector · Apr 23, 2015 · Viewed 8.9k times · Source

I'm creating a basic script that should take 3 mandatory command line options and each one must be followed by a value. Like this:

$ myscript.sh -u <username> -p <password> -f <hosts.txt>

I'm trying to make sure the user is passing those exact 3 options and their values and nothing else, otherwise I want to print the usage message and exit.

I've been reading on getopts and came up with this:

usage () { echo "Usage : $0 -u <username> -p <password> -f <hostsFile>"; }

if [ $# -ne 6 ]
then
        usage
        exit 1
fi

while getopts u:p:f: opt ; do
   case $opt in
      u) USER_NAME=$OPTARG ;;
      p) USER_PASSWORD=$OPTARG ;;
      f) HOSTS_FILE=$OPTARG ;;
      *) usage; exit 1;;
   esac
done

echo "USERNAME: $USER_NAME"
echo "PASS: $USER_PASSWORD"
echo "FILE: $HOSTS_FILE"

I was hoping that if I do not pass any of my 3 "mandatory" options (i.e: -u -p -f) Optargs validation would catch that via the "*)" case. While that is true for other options such "-a","-b", etc.. does not seem to be the case in this particular case:

$ myscript.sh 1 2 3 4 5 6

Getops does not treat that as invalid input and the script moves on executing the echo commands showing 3 empty variables.

How can I capture the input above as being invalid as it is not in the form of:

$ myscript.sh -u <username> -p <password> -f <hosts.txt>

Thanks!

Answer

John1024 picture John1024 · Apr 23, 2015

getopts has no concept of "mandatory" options. The colons in u:p:f: mean that, if one of those options happens to be supplied, then an argument to that option is mandatory. The option-argument pairs, however, are always optional.

You can require that the user provide all three though with code such as:

if [ ! "$USER_NAME" ] || [ ! "$USER_PASSWORD" ] || [ ! "$HOSTS_FILE" ]
then
    usage
    exit 1
fi

Place this code after the while getopts loop.

The Role of *)

I was hoping that if I do not pass any of my 3 "mandatory" options (i.e: -u -p -f) Optargs validation would catch that via the "*)" case.

The *) case is executed only if an option other than -u, -p, or -f is supplied. Thus, if someone supplied, for example a -z argument, then that case would run.