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
a
option does not require an argument, whileb
requires 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
while
loop parses the options until all the options provided have been processed. - 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.