How to use getopts in Bash to handle options and arguments

How to use getopts in Bash to handle options and arguments

In this article, we will look at how getopts works and how to use it to handle various types of options and arguments.

When creating complex Bash scripts, it is often useful to provide users with the ability to pass command-line options and arguments, as is commonly seen in Unix programs. To handle such options, a useful tool is the getopts command, which provides a simple and robust way to parse the options given to a script. In this article, we will look at how getopts works and how to use it to handle various types of options and arguments.

getopts is a Bash built-in designed to parse options in a script, similar to how Unix commands (such as ls or cp) accept options preceded by hyphens (- or --). It allows you to specify single or multiple options, options with arguments, and mandatory or optional options.

Unlike getopt (an older version), getopts is POSIX shell-specific, and works internally in Bash in a more secure and portable way.

The general syntax of getopts is as follows:


getopts "options" variable

  • options: A string that defines the options supported by the script. Letters represent accepted options. If an option requires an argument, the letter will be followed by a colon (:).
  • variable: the variable in which the current option will be stored during parsing.

Let's consider a simple example where our script accepts the options -a and -b, where -b requires an argument:


#!/bin/bash

while getopts "ab:" opt; do
  case $opt in
    a)
      echo "Option -a enabled"
    ;;
    b)
      echo "Option -b with argument '$OPTARG'"
    ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
    ;;
  esac
done

Code explanation:

  1. "ab:": The a option does not require an argument, while b requires an argument (indicated by the : after the b).
  2. $opt: The value of the current option is stored in this variable.
  3. $OPTARG: If an option requires an argument, the value of the argument is stored in this variable.
  4. while: The while loop parses the options until all the options provided have been processed.
  5. case: We use a case construct to handle the different options.

In Bash, it is possible to pass multiple options at once, for example -a -b value can be written as -ab value. getopts handles this behavior automatically.

It is good practice to provide a -h or --help option to explain how the script works. Let's add this option to our example:


#!/bin/bash

usage() {
  echo "Usage: $0 [-a] [-b argument] [-h]" 1>&2
  exit 1
}

while getopts "ab:h" opt; do
  case $opt in
    a)
      echo "Option -a enabled"
    ;;
    b)
      echo "Option -b with argument '$OPTARG'"
    ;;
    h)
      usage
    ;;
    \?)
      usage
    ;;
  esac
done

The -h option calls the usage function which prints a short help and exits the script.

You may need to ensure that some options are required. We can add some logic that checks whether the required option has been supplied:


#!/bin/bash

b_flag=false

while getopts "ab:" opt; do
  case $opt in
    a)
      echo "Option -a enabled"
    ;;
    b)
      b_flag=true
      echo "Option -b with argument '$OPTARG'"
    ;;
    \?)
      echo "Option not valid" >&2
      exit 1
    ;;
  esac
done

# Check if the -b option was supplied
if [ "$b_flag" = false ]; then
  echo "The -b option is required" >&2
  exit 1
fi

If the script is run without the -b option, an error message will be displayed.

Conclusion

Using getopts in Bash allows you to handle script options flexibly and efficiently. We have seen how to parse simple options, options with arguments, handle the helper option, and check for required options. These are just a few of the possible use cases; combining getopts with other Bash features allows you to create robust and user-friendly scripts.