Scripting is an integral part of Linux. As an admin, you’ll soon find yourself using scripts to automate tasks for your specific needs. In an earlier tutorial, we saw how to execute a bash script. But scripts can be even more powerful. Instead of simply being standalone logic that performs set tasks, you can expand their functionality so that they also accept arguments from the user, so you can create a script that reacts flexibly to user input. These arguments take the same form that you’re used to with bash commands – options, flags, etc, have the same syntax, so you can use them as with any other Linux command.
To process these arguments, we have a convenient tool called “getopts”, which we call from within the script to process the arguments one by one. Let’s see how it works.
Syntax for getopts
From within the script, we use getopts in a “while loop like this:
while getopts ...; do ... done"
This is the standard construction. The “getopts” command isn’t a function or anything that returns a value. It’s a specific keyword that we use like this:
while getopts ":af:v" opt; do
This while loop stores the options in the “opt” variable one by one, and then we use a “case” statement to iterate through them. At the same time, if a particular option has an argument as well, getopts stores it in the OPTARG variable.
Defining the Arguments
While calling getopts, we also specify the options that we expect to parse. We use a string where each letter represents an option. If an option requires an argument, then we follow it with a colon (:). So, for example,
getopts ":af:v"
Means that we can expect three parameters or options – “a”, “f”, and “v”. In addition, the “f” option also expects an argument.
Here’s a quick demonstration of a complete getopts usage:
while getopts "a:bc" opt; do
case $opt in
a)
echo "Option -a with argument: $OPTARG"
;;
b)
echo "Option -b"
;;
c)
echo "Option -c"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
esac
done
shift $((OPTIND-1))
In the above code, we’re telling getopts to expect three possible options – a, b, and c, with “a” expecting an argument. For the current “while” iteration, getopts stores the argument in the “opt” variable. We then use a case statement to figure out what the current option is, and act accordingly. Here’s a tutorial on how case statements work in bash.
You can see that the “OPTARG” variable holds the argument of the option.
Best Practices for Using getopts
Getopts can be a bit confusing to get used to. However, there are a few best practices we can use for maximum efficiency and to create error-resistant code.
Using getopts in a “while” Statement
While you can technically use getopts without a while statement, it doesn’t make sense in any other context. Getopts is designed to be used iteratively, one by one, until all the arguments are terminated. The general way it’s used is like this:
while getopts "option_string" opt_var; do ... done
Define your Options Comprehensively
Make sure you include all the various options your script can accept and ensure that you specify those options requiring an argument with a colon (:) after. For example, if you want the user to be able to specify “-f filename.txt”, then use “f:” in the getopts declaration.
Use the “Silent Error Reporting” Mode
By default, getopts will immediately spit out error messages when it encounters an option it didn’t expect, based on the options you specified. This can work fine for quick and dirty scripts, but most of the time, you want to have control over the error messages, and you want to set them programmatically. To do this, we initiate getopts in what we call “Silent Error Reporting” mode, where we preface the set of available options with a colon (:) like this:
getopts ":a:bc"
The colon before “a” indicates to getopts to operate in silent mode, and if it encounters an option that doesn’t belong, you can handle it using the case statements. With the leading colon, getopts sets the option variable and the OPTARG variable as follows:
Invalid option:
If the option is invalid, getopts sets the option variable to “?” and the OPTARG variable to the invalid option.
Missing argument:
Conversely, if the option is valid but missing an expected argument, getopts will set the option variable to a colon (:) and the OPTARG variable to the option character that was missing an argument.
Exit the Script After Encountering an Error
If your user has entered either an invalid option or has omitted providing an expected argument, it’s a best practice to exit the script after printing an appropriate error message. You can exit the script using:
exit 1
You should also print the error message to the standard error stream “stderr” via the “>&2” option. The user can decide whether they want to see the error directly or redirect the error to stdout.
Clean the Positional Parameters After Processing getopts
As getopts runs, it keeps increasing the OPTIND variable. When finished, OPTIND will hold the position of the first non-option argument. These arguments are the “meat” of the command. For example, if you display a text file using the “cat” command, then the filename will be a non-option argument. Without these arguments, commands often have nothing to work on and won’t make any sense.
After getopts runs, you must “clean” the options out of the index so that you can refer to the non-option arguments using $1, $2, etc. If you don’t do this, then you won’t know what the index of these arguments are for the command. To clean up the option parameters, we use the following command:
shift $((OPTIND - 1))
This will throw out all the parameters processed by getopts, and set the first non-option argument to $1. Now your script can access these easily.
Using Getopts for Flexible Scripts
The power of getopts is that it allows your users to run scripts in ways that suit them best. For example, sometimes you want a script to print verbose information about what’s happening, and sometimes you just want it to execute silently. Another example is if you’re about to make a major change with a script, you might want to give the user an option to create a “dry run”, where the script shows you what’s changing without actually making any changes.
In an earlier article, I showed you how to use the bash select loop to create menus in your scripts, allowing users to make choices visually. This is nice, but you might be able to replace this using getopts for a more streamlined (if less user-friendly) experience. Once you start creating your own scripts for your workflows, you’ll soon come to see the power of getopts.
Conclusion
When you start creating scripts, you’ll soon find the need to let your users customize the way the scripts work, just as with regular Linux commands. The way to process option parameters and arguments is by using getopts. This will let your users decide the precise manner in which the script must be run. While you can use the bash select loop to create a menu, using flags is cleaner and faster.

I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!

Leave a Reply