How to Use “getopts” in Bash [Complete Guide]

The getopts command is widely popular for parsing command-line options and arguments. However, unlike many other Bash built-ins, it is not a beginner-friendly command. Users need to understand the syntactical nuances of it. Moreover, this command is often associated with loops and case statements, which makes it even harder to grasp. This article aims to clarify the concepts of getopts and delve deeper into writing real-world scripts involving getopts to parse options and arguments.

What is “getopts” in Bash?

The getopts command is a shell built-in in Bash. It allows users to specify options and arguments that a script can accept. getopts has leverage over the positional parameter due to multiple reasons. First of all, it can easily handle options or flags (prefixed with a hyphen) and modify script behavior. Moreover, getopts can receive arguments, also known as parameters, to provide specific data to the script following an option or flag.

How Does “getopts” Work in Bash?

Before understanding the working principle of the getopts command, you must know its syntax:

getopts optstring optname [ arg ]

Here, the optstring contains the option letters. getopts looks for one option at a time from the command line arguments. It is important to note that getopts is typically used in association with a while loop. On each iteration of the loop, getopts assigns the currently processed option to the variable optname declared immediately after the optstring. For instance:

getopts "ui" flag

In this example, the optstring is “ui”. While iterating over the “ui” using a while loop, the variable flag can take the value u or i or both depending on what users provide when executing the script. See the complete Bash script illustrating this:

#!/bin/bash
while getopts "ui" flag; do
  echo $flag
done

optname in each iteration of getopts command in BashIn the first execution, the variable flag takes the value u only, because only option -u is given as a command-line argument while executing the script.

In the second case, both -u and -i are provided as options during the execution of the script. Therefore, “flag” takes the values u and i respectively.

Finally, when no option is provided, the script prints nothing as no command line option matches with the optstring “ui”

Parsing a Single Option to Bash Script Using “getopts”

Inside the getopts command, a case statement is useful to redirect the execution path of a script based on options. When an option specified in the optstring is found in the command-line arguments, the case statement matches the option and executes specific tasks defined for that option. Here’s an example of parsing a single option:

#!/bin/bash

while getopts "a" flag; do
case ${flag} in
 a) echo "Option -a is triggered."
     # code block for option -a
   ;;
esac
done
EXPLANATION

The Bash script specifies a single option “a” in the optstring of the getopts command. It utilizes a case statement with the getopts command to print a message if option “-a” is encountered in the command-line arguments.

Parsing a single option using getopts in BashAs expected executing the script with option -a displays that “Option -a is triggered.”.

How to Handle Multiple Options with “getopts” in Bash?

To handle multiple options with the getopts command, you can use a case statement to match each option and execute specific tasks for each of them. Here’s an example of parsing three different options:

#!/bin/bash

while getopts "abc" flag; do
case ${flag} in
 a) echo "Option -a is triggered."
   ;;
 b) echo "Option -b is triggered."
   ;;
c) echo "Option -c is triggered."
   ;;
esac
done
EXPLANATION

The getopts command of the above script is used to parse command-line options -a, -b, and -c. Inside the while loop, each option encountered in the command line is matched using a case statement. For option -a, the script prints a message indicating that it has been triggered. Similarly, for options -b and -c, corresponding messages are printed when they are encountered.

Handling multiple options using getopts command in Bash

Executing the script with options -b and -c echoed the messages written for those options inside the case statement. Option -a is missing in the command-line arguments. Therefore, the message written for option -a is not printed.

Note: During execution providing multiple options in a single argument like -bc triggers both options.

Parsing Options with Argument Using OPTARG of “getopts” in Bash

Sometimes options take additional arguments or parameters. To provide an argument to an option, place a colon (:) after the option letter in the optstring. In getopts, if a letter in the optstring is followed by a colon :, it indicates that the option expects an argument. For the optstring "u:i", if the option -u is triggered then it is mandatory to provide an argument. Whereas optsting "u:i:" means if triggered both -u and -i require arguments.

When an option takes an argument, the argument is accessible by the output-only variable OPTARG of the getopts command. Here is an example combining all this information:

#!/bin/bash

# Parse command-line options
while getopts ":f:d:" opt; do
  case $opt in
    f) echo "The filename is: ${OPTARG}"
      ;;
    d) echo "The directory is: ${OPTARG}"
  esac
done
EXPLANATION

The Bash script utilizes the getopts command to parse command-line options. It specifies two options, -f  and -d in the optstring. As there is a colon (:) after both options, if triggered each of them requires an argument.

Inside the loop, a case statement is used to check the currently processed option. If the option -f is encountered, the script prints out the filename specified with the option using the special variable OPTARG. Similarly, if the option -d is found, the script displays the directory provided with the option using OPTARG.

Parsing option with argument using getopts in Bash

Executing the script without providing the argument for option -f shows that “option requires an argument – – f”. In the second execution, option -f is provided with the argument file1.txt, and option -d is given with the argument /home/laku. While processing the option -f OPTARG holds the value “file1.txt”. On the other hand, while processing option -d the value of the variable OPTARG becomes “/home/laku”.

Note: As colon (:) is used for the purpose of taking an additional argument for options, it should not be used as an option letter. Therefore, avoid using colon (:) as option characters in the optstring like ":".

It is recommended to put a space between an option and its argument. For instance, if the getopts string is “f:”, the -f option anticipates an argument, which should be provided separately as -f arg. However, if getopts can identify an option, it will interpret the subsequent characters as an argument, even if it’s a single argument in the command line. Hence, for the getopts string “f:”, both -f arg and -farg would be perceived as providing an argument to the -f option. Look at the following execution to make it clear:Spacing between option and argument in getopts in Bash

As you can see, there is no space between option -f and its argument “file1.txt”. But getopts has identified the option and stores the option argument “file1.txt” in OPTARG.

Use of OPTIND with Bash “getopts” Command

OPTIND is another special variable of getopts command that stores the index of the first unprocessed option or argument in the command line. It is initialized to 1 and may or may not increase on each iteration depending on the position of the next unprocessed option in the command line arguments. Clear your concept about OPTIND with the following script:

#!/bin/bash 
while getopts "ab:c" flag; do
         echo "$flag" $OPTIND $OPTARG
done
EXPLANATION

The script utilizes the getopts command to parse command-line options with a while loop. As each option is processed, the script echoes three pieces of information: the current option ($flag), the index of the next argument ($OPTIND), and the value of the option’s argument ($OPTARG). In the getopts string, "ab:c", option ‘a’ is a flag without an argument, ‘b’ is a flag that expects an argument, and ‘c’ is a flag without an argument. As the script iterates through the command-line options, it prints each option, the index of the next argument, and the value of the argument (if any).

OPTIND variable of getopts in BashFor command-line argument: -ac -b BB Null

Here, arg1 is -ac, arg2 is -b, arg3 is BB and arg4 is Null.

While processing option -a, the first unprocessed option is -c which is in arg1. So the index stored in OPTIND is 1. For the following option -c, the first unprocessed option is -b which is arg2. So the index stored in OPTIND is 2. Finally, for the next option -b, the first unprocessed argument is Null which is arg4. Because while processing option -b, arg3 (“BB”) is processed as an argument of option -b. That’s why OPTIND stores 4 or the index of arg4.

For the command line arguments -ab BB -c Null and  -a -b BB -c, things work similarly.

The OPTIND variable is super useful to process non-option arguments after parsing the options. Here is an example:

#!/bin/bash
while getopts "ab:" flag
do
    case ${flag} in
    a)   echo "Option -a specified."
          ;;
    b)   echo "Option -b specified with argument: $OPTARG"
          ;;
    esac
done
shift $(($OPTIND - 1))
echo "Remaining arguments are: $*"
EXPLANATION

The Bash script utilizes the getopts command to parse command-line options. Within a while loop, each option and its associated argument are processed. If option -a is specified, the script prints a message indicating its presence. For option -b, the script prints a message along with the argument provided with it, accessed via the special variable $OPTARG. After processing the options, the script shifts the index to the first unprocessed command-line argument using shift $(($OPTIND - 1)), allowing it to access any remaining arguments. Finally, it prints out the remaining arguments using $*, indicating the arguments that are not associated with any options.

Processing extra argument using OPTIND in getopts command in Bash

When the script is executed with the arguments -ab Null, after processing the options, there is no remaining argument.

Similarly, for the command line arguments -b 2 -a 5, after processing the options and option argument, 5 is left. The shift $(($OPTIND - 1)) command makes 5 accessible using the first positional parameter ($1).

Silent Error Handling of “getopts” in Bash

There are two ways to handle errors in getopts command. By default, getopts reports an error when an invalid option is found or if there is any missing argument. For instance:

#!/bin/bash
while getopts "f:" opt; do
  case ${opt} in
    f ) echo "The given file is ${OPTARG}"
        ;;
  esac
done

Default error handling mode of getopts in Bash

Here, -l is not a valid option. Option -f is valid but requires an argument. By default, getopts displays the error messages in the terminal. However, if a leading colon (:) is placed in the optstring getopts won’t show the error messages in the terminal as the leading colon enables the silent error handling mode. Look at the following example:

#!/bin/bash
while getopts ":f:" opt; do
  case ${opt} in
    f ) echo "The given file is ${OPTARG}"
        ;;
  esac
done

Enabling silent error handing mode of getopts in Bash

As the optstring is ":f:", definitely the option -f requires an argument. Though the argument is not provided the execution doesn’t show any error due to the leading colon in the optstring.

When silent mode is activated, colon (:) is stored in the variable defined after optstring for missing argument, and question mark(?) is stored for invalid option. In such situations, OPTARG is set to the option character found. The following example demonstrates all this at once:

#!/bin/bash
while getopts ":f:" opt; do
  case ${opt} in
    f ) file=$OPTARG
        echo "The given file is ${file}"
      ;;
   \? )
      echo "Invalid option: $OPTARG"
      ;;
   : )
      echo "Invalid option: $OPTARG requires an argument"
      ;;
  esac
done
EXPLANATION

In the optstring ":f:", silent mode is enabled due to the leading colon (:). The case statement within a while loop handles three patterns: when a valid option with an argument is provided (-f with an argument), when an invalid option is provided (\?), and when the option -f is provided without the required argument (:). When a valid option (-f) with an associated argument is encountered, the script assigns the argument to the variable file and prints a message indicating the provided file. In case of an invalid option, it prints an error message specifying the invalid option using OPTARG. Lastly, when option -f is provided without the required argument, again it prints an error message indicating the necessity of an argument for the option using OPTARG.

Error handing in silent mode of getopts command in Bash

The image shows that -r is an invalid option as it isn’t specified in the optstring. The OPTARG variable retrieves the option itself. Furthermore, when -f is provided as an option without argument it matches the pattern colon (:) of the case statement and prints that the option requires an argument.

3 Practical Usage of “getopts” Command in Bash

The getopts command is primarily used for parsing command line options. It can perform the task more elegantly than any other method. Below are a few such examples:

Example 1: Parsing Named Parameter

To parse named parameters use the getopts command and assign their values to specific variables. Use OPTARG to assign the value of parameters to named variables like below:

#!/bin/bash

while getopts "u:p:" flag; do
   case "${flag}" in
       u) User=${OPTARG};;
       p) Password=${OPTARG};;
   esac
done
EXPLANATION

This Bash script defines two options in getopts, -u for specifying a username and -p for specifying a password. Within the loop, the script examines each provided option and assigns its value to corresponding variables using the OPTARG variable. Once all options are processed, it prints out the password associated with the specified username.

Parsing named parameters using getopts command in Bash

Parameters “Anita” and “jk5279” are provided as arguments of the flags -u and -p respectively. The output shows that these parameters can be further processed after assigning them to variables.

Example 2: Parsing Long Options

The getopts command doesn’t support long-form options. However, users can specify a hyphen (-) as an option character and use a nested case statement to process the long-form options along with the short-form. Here is how it works:

#!/bin/bash

while getopts ":vfV-:" opt; do
  case $opt in
    v|version)
      echo "Bash version: $BASH_VERSION"
      ;;
    f|force)
      echo "Force execution confirmed."
      ;;
    V|verbose)
      echo "Verbose mode activated."
      ;;
    -)
      case "${OPTARG}" in
        version)
          echo "Bash version: $BASH_VERSION"
          ;;
        force)
          echo "Force execution confirmed."
          ;;
        verbose)
          echo "Verbose mode activated."
          ;;
        *)
          echo "Invalid option: --$OPTARG"
          exit 1
          ;;
      esac
      ;;
    \?)
      echo "Invalid option: -$OPTARG"
      exit 1
      ;;
  esac
done
EXPLANATION

This Bash script is designed to handle long and short forms of command-line options using the getopts command. It begins by setting up the options it expects to receive: -v, -f, -V, and their corresponding long forms (– -version, – -force, – -verbose). Inside the loop, it evaluates each option provided through the command line using a case statement. If the option matches one of the defined short forms, it executes the corresponding action.

For handling long-form options the script specifies hyphen(-:) as an option character that takes an additional argument. In the nested case statement, if the option matches one of the defined long forms it executes the corresponding action. If an invalid option is detected, it outputs an error message and exits with a status code of 1.

Handling long and short form of options using getopts command in Bash

As expected both long-form and short-form options give the same result. When the script is executed with option -v it prints the version of Bash. Executing the script with the corresponding long form of option -v (- -version) also displays the version of Bash. Other options show the same behavior.

Example 3: Showing User Manual of a Script with “-h” Option

Complex and lengthy Bash scripts should have a user manual. The user manual of a script can be easily maintained using the getopts command. It ensures when users provide options such as -h or – – help it should display the documentation of the script itself. To have an idea about how it works see the script below:

#!/bin/bash

# Function to display help text
usage() {
    echo "Usage: $0 [-v] [-V] [-f] [-h]"
    echo "Options:"
    echo "  -v           Display Bash version."
    echo "  -V          Enable Verbose mode."
    echo "  -f            Continue force execution."
    echo "  -h           Display the help message"
}

# Parse options using getopts
while getopts ":vVfh" option; do
    case "${option}" in
        v)  echo "Bash version: $BASH_VERSION"
            ;;
        V)  echo "Verbose mode activated."
            ;;
        f)  echo "Force execution confirmed."
            ;;
        h)  # Help option
            usage
            exit 0
            ;;
        \?) # Invalid option
            echo "Invalid option: -$OPTARG"
            usage
            exit 1
            ;;
    esac
done
EXPLANATION

This Bash script defines a function called “usage” to display a help message detailing the script’s usage and available options. It then utilizes the getopts command to parse command-line options, including -v (to display the Bash version), -V (to enable verbose mode), -f (to confirm force execution), and -h (to display the help message). Within the getopts loop, each option is handled in a case statement, executing the corresponding action based on the provided option. If an invalid option is detected, it outputs an error message along with the usage information and exits with a non-zero status code.

Displaying user manual of a script using getopts command in Bash

In the first execution, option -h is triggered. Hence the script calls the usage function and prints the user manual of the script.

Conclusion

In conclusion, the getopts command is handy for parsing options and arguments. It has a couple of special variables such as OPTARG and OPTIND that make the task easy. Moreover, one can handle errors of getopts command in multiple ways. Once you learn the basic working principle of getopts you can use it in various argument parsing situations.

People Also Ask

What is the use of the getopts command?

The getopts command is used in shell scripting to parse command-line options and arguments. It allows scripts to handle command-line arguments more efficiently by recognizing specified options and their arguments.

What are the differences between getopt and getopts?

The difference between getopt and getopts is that, getopt is a C library function for parsing command-line options and arguments. It is also available in Bash shell. On the other hand, getopts is a shell built-in command available in Bash shell for parsing command-line options. The syntax of getopt is somewhat complex whereas getopts is straightforward. The getopt function can handle complex parsing scenarios. On the contrary, getopts serves the purpose of parsing simple command-line options in shell scripting.

Which one is better for parsing options in Bash, getopts or getopt?

The getopts command is better for parsing simpler options and arguments in Bash. However, getopts can’t directly handle long-form options. If a script requires parsing long-form options then it is better to choose getopt.

Can multiple colons be used after an option letter to specify multiple arguments in getopts?

No, in getopts, you can only use a single colon after an option letter to indicate that the option requires an argument. Multiple colons are not supported for indicating multiple arguments though it won’t show an error. Each option can only be associated with a single argument. For example, optsring “f::” doesn’t mean option -f can take two arguments. It will still take a single argument like the optstring “f:”. In getopt, a double colon after an option letter makes the argument optional. But in getopts it doesn’t.

What does shift $(($OPTIND -1)) actually do?

The command shift $(($OPTIND - 1)) in shell scripting discards processed command-line options, enabling access to the remaining arguments using positional parameters.

Related Articles


<< Go Back to Argument in Bash Script | Bash Functions | Bash Scripting Tutorial

Rate this post
LINUX
FUNDAMENTALS
A Complete Guide for Beginners Enroll Course Now
Md Zahidul Islam Laku

Hey, I'm Zahidul Islam Laku currently working as a Linux Content Developer Executive at SOFTEKO. I completed my graduation from Bangladesh University of Engineering and Technology (BUET). I write articles on a variety of tech topics including Linux. Learning and writing on Linux is nothing but fun as it gives me more power on my machine. What can be more efficient than interacting with the Operating System without Graphical User Interface! Read Full Bio

Leave a Comment