Create a Bash Script that Accepts Named Options with getopts

Cameron Nokes
InstructorCameron Nokes
Share this video with your friends

Social Share Links

Send Tweet
Published 6 years ago
Updated 4 years ago

Let’s say you want to allow a user to pass a -v flag to turn on verbose logging in a script. Manually parsing out options passed to a script is difficult, but in this lesson, we’ll learn about getopts which makes it easy. We'll look at the limitations of using getopts (options must be in a format like -a or -ab <value>) as well as the importance of shifting processed options off of the argument array.

Instructor: [00:00] To use Getopts, we invoke it in a while loop. I'll say while getopts. Then we pass in a string. In the string, we'll pass the options that our script supports, and then Getopts will parse for us. We'll just do an a for now, and then we'll pass the name of the variable that we want each option to be assigned to. We'll just use opt there.

[00:24] Here, we'll process each option. I'm going to use a case statement. Then we'll handle our a here, close our case statement. We can see, I have my Getopts script there already. Then lets invoke getopts and pass the a option.

[00:42] We can see that it's working. Let's see what happens if we don't pass any options. Nothing happens, just the script runs successfully, but no options are found. Then if I pass an unknown option, we see that it's outputting this illegal option. Also note that the exit status of the script is not set to a one or anything.

[01:02] A lot of people like to disable this default behavior of Getopts. The way we do that is we prepend this list here with a colon. That tells Getopts that we want to handle the unknown option error case on our own.

[01:16] The way for us to do that is we check for the question mark. This opt variable will be sets to a question mark if it receives an unknown option. Note that we have to escape the question mark, just because it's a special Bash character.

[01:32] Let's come back here, and we'll do getopts a and b. We can see a is found and working like normal, but now, when we pass it b, it just says unknown option. Getopts also supports passing a value to an option.

[01:50] Let's do b, and then we're going to add a colon after b. That tells Getopts that this b flag expects a value to be passed to it as well. Let's handle b here. We'll say b. I'm going to say b found, and the value is.

[02:06] The value is going to be found in this optarg variable that Getopts sets. As Getopts iterates through this, will set and reset this opt arg variable as needed. When it gets to b, and it finds a value passed to it, that value will be contained in this optarg.

[02:25] Let's try it out. Do getopts. We'll do a again, and then to b, we'll just pass a one, two, three string. Cool. We can see that that's working. Note that only single character and single dash options are supported by Getopts.

[02:42] There's a lot of different formats for passing options to scripts. Something like that is common, or this. These option formats, though, aren't supported by Getopts. It has to be single dash and single character, like that.

[03:01] After our Getopts while loop, it's good practice to shift the options out of the arguments array. That way, if our script accepts additional parameters, we can just process those next. We use the shift builtin, and we do a little bit of math here.

[03:16] We say optindex minus one. optindex is a variable set by Getopts. It represents the index of the last processed option. Basically, it'll be equal to the number of options that were processed in total. What this does is, it's going to take all of our options and their values, and it shifts it out of the arguments array.

[03:36] For example, if we then wanted to process additional arguments, we could do a for-loop, for arg in the arguments array. We'll just do an echo here. If we do that again, we see this still works. If we wanted to pass a list of just anything here, we could see that that works.

[03:55] It processed our options just fine. Then after that, we have a separate list that needs to be processed. That happens by our for-loop. We can see that that's working there as well. Jumping back to our script here, if we did not have this shift here, let's see what would happen.

[04:12] We can see it processed our Getopts just like we expected, but then after we're done processing these, we're done with them. We want them to be out of the arguments array. Because we didn't shift them, we can see that these got processed again by the for-loop.

[04:28] We shift those off, we run it again, and we can see that it behaves just like we want it to.