Bash getopts builtin command

Updated: 12/29/2017 by Computer Hope

About getopts

getopts is a builtin command of the Bash shell which parses command options and arguments. It is useful for creating bash scripts.

getopts is the bash version of another system tool, getopt. Notice that the bash command has an s at the end, to differentiate it from the system command.

While the getopt system tool can vary from system to system, bash getopts is defined by the POSIX standard. So if you write a script using getopts, you can be sure that it will run on any system running bash in POSIX mode (e.g., set -o posix).

getopts parses short options, which are a single dash ("-") and a letter or digit. Examples of short options are -2, -d, and -D. It can also parse short options in combination, for instance -2dD.

However, getopts cannot parse options with long names. If you want options like --verbose or --help, use getopt instead.

Syntax

getopts optstring name [ arg ]

Basic overview

getopts processes the positional parameters of the parent command. In bash, this is stored in the shell variable "[email protected]". So, if you run this command:

mycmd -a argument1 -b argument2

During the time that mycmd is running, the variable [email protected] will contain the string "-a argument1 -b argument2". You can use getopts to parse this string for options and arguments.

How it works

Every time you run getopts in your script, it looks for one of the options defined in optstring; if it finds one, it places the option letter in a variable named optname. If the option takes an argument, it looks for that argument and places it in $OPTARG. It increments the option index, $OPTIND, which points to the next option to be processed.

The special option of two dashes ("--") is interpreted by getopts as the end of options.

getopts is designed to be run multiple times in your script — in a loop, for instance. It processes one option per loop iteration. When there are no more options to be processed, getopts returns false, which will automatically terminate a while loop. For this reason, getopts and while are frequently used together.

Specifying the optstring

optstring is a string which defines what options and arguments getopts will look for. For instance, in this call to getopts:

getopts "apZ" optname

The options expected by getopts are -a, -p, and -Z, with no arguments. These options can be combined in any order as -aZ, -pa, -Zap, etc.

Let's say that you'd like the -a and -Z options to take arguments. You can specify this by putting a colon (":") after that option in optstring. For example:

getopts "a:pZ:" optname

Now you can specify arguments to the -a and -Z options such as -a argument1 -pZ argument2. The -p option cannot take arguments, because there is no colon after the p in optstring.

Note: There are two reserved characters which cannot be used as options: the colon (":") and the question mark ("?").

Verbose error checking

By default, getopts will report a verbose error if it finds an unknown option or a misplaced argument. It will also set the value of optname to a question mark ("?"). In does not assign a value to $OPTARG.

If the option is valid but an expected argument is not found, optname is set to "?", $OPTARG is unset, and a verbose error message is printed.

Silent error checking

However, if you put a colon at the beginning of the optstring, getopts will run in "silent error checking mode." It will not report any verbose errors about options or arguments, and you will need to perform error checking in your script.

In silent mode, if an option is unexpected, getopts will set optname to "?" and $OPTARG to the unknown option character.

If the option is OK but an expected argument is not found, optname is set to a colon (":") and $OPTARG is set to the unknown option character.

Specifying custom arguments

You will usually want getopts to process the arguments in [email protected], but in some cases, you may want to manually provide arguments for getopts to parse. If so, you can specify these args as the final argument of the getopts command.

Examples

Here is a bash script using getopts. The script prints a greeting, with an optional name, a variable number of times. It takes two possible options: -n NAME and -t TIMES.

#!/bin/bash

NAME=""                                          # By default, NAME is empty
TIMES=1                                          # By default, print greeting once

usage() {                                        # Function to print a usage string.
  echo "Usage: $0 [ -n NAME ] [ -t TIMES ]" 1>&2 # Echo usage string to standard error
  exit 1                                         # Exit with error status 1
}

while getopts ":n:t:" options; do                # Our getopts while loop
  case "${options}" in                           
    n)                                           # If the option is -n
      NAME=${OPTARG}                             # set $NAME.
      ;;
    t)
      TIMES=${OPTARG}                            # set $TIMES.
      re_isanum='^[0-9]+$'                       # regex to match whole numbers only
      if ! [[ $TIMES =~ $re_isanum ]] ; then     # if $TIMES is not a whole number...
        echo "Error: TIMES must be a positive, whole number."
        usage
      elif [ $TIMES -eq "0" ]; then              # If it's zero...
        echo "Error: TIMES must be greater than zero."
        usage
      fi
      ;;
    :)                                           # If expected argument omitted...
      echo "Error: -${OPTARG} requires an argument."
      usage
      ;;
    *)                                           # If neither option is matched...
      usage
      ;;
  esac
done

if [ "$NAME" = "" ]; then                        # If $NAME is an empty string,
  STRING="Hi!"                                   # our greeting is just "Hi!"
else
  STRING="Hi, $NAME!"                            # otherwise, it includes $NAME
fi

COUNT=1                                          # Counter variable 
while [ $COUNT -le $TIMES ]; do                  # While less than or equal to $TIMES,
  echo $STRING                                   # Print a greeting, and
  let COUNT+=1                                   # increment the counter.
done

exit 0                                           # exit normally

If this script is named greeting, here's what the output will look like with different options:

./greeting
Hi!
./greeting -n Dave
Hi, Dave!
./greeting -t 3
Hi!
Hi!
Hi!
./greeting -t 4 -n Betty
Hi, Betty!
Hi, Betty!
Hi, Betty!
Hi, Betty!
./greeting -n
Error: -n requires an argument.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
./greeting -t
Error: -t requires an argument.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
./greeting -t -1
Error: TIMES must be a positive, whole number.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
./greeting -t 0
Error: TIMES must be greater than zero.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]

which — Execute a set of actions while a certain condition is true.