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:
- "ab:": The
aoption does not require an argument, whilebrequires an argument (indicated by the:after theb). - $opt: The value of the current option is stored in this variable.
- $OPTARG: If an option requires an argument, the value of the argument is stored in this variable.
- while: The
whileloop parses the options until all the options provided have been processed. - case: We use a
caseconstruct 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.