Parsing Command Line Options with getopts - Part II
Start course
2h 42m

In this course, we'll cover a range of topics designed to help you enhance your Linux scripts. We'll start off by looking at case statements, which are used to make a decision based on the value of a given variable. We'll cover functions before moving and then move on to how to process command-line options using the shell built-in getopts.

In the second part of the course, we'll look at managing users including how to disable, delete, and archive users on a Linux system. We'll then do a walkthrough exercise showing you how to delete a user, which you can follow along with.

This course is part of the Linux Shell Scripting learning path. To follow along with this course, you can download all the necessary resources here.

Learning Objectives

  • Learn about case statements and functions to make your scripts more efficient
  • Process command line options using getopts
  • Manage users in Linux

Intended Audience

  • Anyone who wants to learn Linux shell scripting 
  • Linux system administrators, developers, or programmers


To get the most out of this course, you should have a basic understanding of the Linux command line.


Let's say we want to add two numbers together and assign them to a variable. So we can do this like this, we'll create a variable right here on the command line then we'll call it num, and we'll follow that with dollar sign, opening parenthesis, opening parenthesis, and then an expression here, one plus two, and we'll close that with these double parentheses here. So this dollar sign, parenthesis, parenthesis, syntax is called arithmetic expansion. Bash evaluates the arithmetic expression within the double parentheses and it returns or substitutes the answer in its place. So now num, the variable num, should contain the value of three and we can check it like so. And sure enough it does. Okay, let's do some subtraction. We'll set num equal to ten minus one and the value of that is nine. Multiplication is handled with an asterisk. So let's do that. two times four is eight. Division is handled with a forward slash, so we can do this. Let us talk about this particular situation. So we'll do six divided by four and then bash returns one. So six divided by four is actually 1.5, but again bash just returned one to us. So here's what you need to know, bash doesn't do any rounding, it just drops off the decimal point and anything after it. So really bash doesn't support floating point arithmetic. That's usually fine because what you'll end up doing most of the time is very simple math like adding two numbers together, or incrementing a number by one during a loop and things like that. If you need to work with numbers that contain a decimal then you're going to need to use an external program such as bc, which stands for basic calculator. Now it might not be installed by default so if you do this, type dash a, bc, and you don't see it there, then what you would need to do is, sudo yum install dash yes, or dash y, excuse me, bc, to install it. So here I have it installed, but you may not. Again, you may need to install it. So let's get some help on this thing here, dash h. If you wanna do floating point math with bc, you have to turn on the math libraries with the dash l option. Also, it's important to know that bc reads from standard input. So you can do things like this. We can do echo six divided by four and we'll pipe that into bc and we'll use the dash l option. and it returns 1.5. By the way, if you need a quick calculator at the command line, you can just run bc dash l and then do that here as well, six, four, or one plus one, or whatever you wanna do. And then you can type control d to exit out of the calculator here. Quickly, you can also use opt to do this. It's a little bit more cumbersome but I'm just gonna show you quickly how to do it and you can stock it away if you wanna use it at some time. Again, I don't necessarily recommend doing this but you may see this in other people's shell scripts. So we can use this awk, begin, and then what we wanna do is print six divided by four, and that is 1.5. So whether you're using bc or awk you get the full and complete answer. Now let's get back to bash. So six divided by four, according to bash is one. There is a remainder though when you do six divided by four and you can get that remainder with the percent sign, also known as modular or the modular operator. So we can do this, num equals six modular four, and that is going to be two. It prints two because six divided by four is one with two leftover, or a remainder of two. Now this comes in handy when you want to do alternating things, for example you could treat all even numbers one way and all odd numbers in a different way. Even numbers divided by two, always have a remainder of zero while odd numbers divided by two, have a remainder of one. Then you could use a simple f or k statement to handle those different situations. By the way, you don't have to use hard-coded numbers like I've been doing here. You can also use variables inside the parentheses too. So we can do this, something like this: Dice A is equal to three, dice B is equal to six and the total of those die would be dice A plus dice B. And of course, six plus three is nine. You might have noticed here that I didn't use a dollar sign for dice A or dice B. Those are variables inside those double parentheses, you don't do that when you're using this particular syntax. By the way, you can assign or change the value stored in a variable. Here, you don't need the leading dollar sign. That leading dollar sign is used for substitution but we don't want to substitute the command for its value, we just want to change a variable. Hopefully just seeing it here will make more sense, it'll be clearer than me trying to talk through it. So let's do this. Let's set num equal to one, and let's increment the value stored in the variable num by one, and we do this by parenthesis, parenthesis, num plus plus, and then the closing parentheses here. And let's echo this so now num is two. So we've changed the variable without doing any output when we're using the double parentheses syntax but it still affects the variable. Now let's decrement the value stored in the variable, num, by one, and we can do this with dash, dash, or minus, minus, and then two minus one is one, and there we are, we have one stored in the variable, num. Let's add a number to the value of the variable and store that new value in the variable. So we can do this, num plus equals five. So one plus five is six, and we assign that to num and that is what is stored there. You can also do things like minus equal, asterisk equal, which is multiply, forward slash equal, which is division modular equal, and so on. Now, if you wanted to, you could actually use substitution to change the value of the same variable and it would look like this. We could do this, num is equal to dollar sign, these parentheses, num plus equals five. And that is 11, 'cause six plus five is 11. What this does is it takes the output of the num plus equals five, operation, and assigns it to the variable, num. If that seems clear to you, you can do it that way as well or you can use the other syntax that I was just demonstrating. Now, before we wrap up our discussion on math, I wanna show you two other ways to perform math operations that you might encounter in other scripts. The first way is with a let bash built in. You can see all the operators that are supported by doing this. We'll just get some help on it, help let and we'll pipe that to less. So you can see here, the post increment operator of plus plus, the pre increment of plus plus, that's before, for the variable name, you know, plus and minus the exponentiation, all these things that we're doing here, and these things that we were doing here like plus equals, minus equals, and so on. Now, this let syntax pretty much does the same thing as using double parentheses. So let's do this, let num equals two plus three, and sure enough that sets num to five. You can also do this, let num plus plus, and that increments it by one, so now we have num with a value of six. The second way you'll see math performed in scripts is with the expr command. The double parentheses syntax we've been using is built into bash, and that's the route I recommend if at all possible. However, you can rely on external programs like we'd saw earlier with bc. So the expr command processes an expression given to it and then sends that result to standard out. So expr one plus one, it returns two. Now to do assignment, we just use command substitution like we would with any other command. So we'll do num, normal command substitution syntax, and again, two plus three returns five that is assigned to num, and that is what is displayed when we access the value stored in that variable. Okay, so that was a pretty long aside, but we needed to cover it before we could get back to getopts, and let's do that now. Getopts does not change positional parameters. What this means is that the options are stored in dollar sign add sign, dollar sign one, dollar sign two, and so on. So let's add a bit of code into our script to kinda prove this and point it out. So right here, after our while looping case statement, let's do this, echo, the number of arguments is stored in dollar sign pound sign. The contents of all the arguments is stored in dollar sign add sign. The first argument is stored in dollar sign one. Second argument is stored in positional parameter dollar sign two. So now let's exit our script and see what this does. So we'll do this, l user demo 11 dash sl eight, and we'll just type some extra stuff if you will, at the end of the command line. So here we have three arguments, dash sl is stored in dollar sign one, eight is stored in dollar sign two, and extra dash stuff is stored in dollar sign three. In my mind, once the arguments are processed, they should be removed as a positional parameter. Now getopts doesn't do this for us but it gives us a way to do it. So let's jump back into our code, getopts sets a variable named opt ind. It stores the position of the next command line argument following the options in that variable. So let's look at its value in action. So we'll run our same command here and opt ind is set to three because the third argument is the index or position where the argument start after the options. If we want to remove the options that have been processed that means we need to shift them down by two. So stated mathematically, that's opt ind minus one. Now let's see if this little formula holds in some other examples. So let's do this, let's just use dash s and then some extra stuff. So sure enough, opt ind is two, so if we subtract one from two, that leaves us with one, and if we shift by one, then what's left is anything supplied after the options. Now let's just run it with just some extra stuff without any options that we're checking for. Now, in this case, like I said, there are no options and nothing needs to be shifted. However, our little formula still works because opt ind is one, one minus one is zero, and if we shift by zero, we change nothing, which is exactly what is needed for this case as well. So let's add this little bit of code or this formula or this algorithm, if you will, to our script. So we're going to shift by the number of opt ind minus one. Now we can process dollar sign add sign, dollar sign one, dollar sign two, and so on, just like we've always done. Now, let's display the contents of dollar sign add sign, et cetera, after the shift. So we'll do this, echo after the shift, and we'll just grab all these up here and print them to our screen again. So now let's use l user demo 11 dot sh, dot sl eight, extra dash stuff. So sure enough, that works. The number of arguments we have at the beginning is three, again, dash sl is stored in dollar sign one, dollar sign two is eight, dollar sign three evaluates to extra stuff. So after getopts is done, and we process all those arguments, the only thing we're left with is extra dash stuff, which after we do our shift is assigned to dollar sign one. And that's exactly what we want. So then we could do things like loop through all the other remaining arguments on the command line with a while loop, for example, while dollar add sign. We could then make people do things like after all your options then we require you to give us a file or a username or whatever that we expect in dollar sign one. Then we can test and do some work against dollar sign one and so on and so forth. However, let's say in this particular script, we want to treat anything other than the options on the command line as an error, and the easiest way to do that is to test the dollar sign pound sign value. So let's jump back into our script and say, if... If the number of arguments is greater than zero then we're going to give them the usage statement and we'll get out of here. Again, we're going to reuse the usage function since it teaches the user how to use the script the way we want them to, and then it exits with a non zero exit status. And remember when you use shift the number of arguments changes and that also updates the dollar sign pound sign variable. So this is going to work. Now, before we test our updated script let's clean up our debugging and development code here, all these little echo statements, and make sure everything is all cleaned up. So let me go up here, we'll get rid of that. And we don't need these lines as well. Now let's do this, let's run it with an argument. So here it gives us the usage just like we want. Of course we exit with a non-zero exit status because it's using that usage function that we created at the top of our script. So let's do something like this, let's say, we'll pass a valid option and then also append stuff to the end of the line here. And sure enough, it gets to that point where it's looking at the number of arguments after we've processed the command line options, and that has triggered the calling of the usage function as well. So let's go ahead and do this with something that is proper, a dash s. And sure enough, we get our password with a special character appended to it. Let's do a quick recap. In this lesson you learned how to use getopts to process command line options. You learned how to wrap the getopts command in a while loop and use a case statement to perform different actions for each option. When you want an option to take an argument you follow that option letter with a colon and the opts string. You also learned how to strip away the options from the set of positional parameters by using the opt ind variable provided by getopts. Finally, you learned how to perform mathematical operations. You learned that you could assign the result of an arithmetic evaluation to a variable by using the dollar sign double parentheses syntax. In addition to hard-coding numbers in your expressions, you also performed arithmetic using variables. You even learned how to change the value stored in a variable directly, using a few different operators including the increment, decrement, and the plus equal operators.

About the Author
Learning Paths

Jason is the founder of the Linux Training Academy as well as the author of "Linux for Beginners" and "Command Line Kung Fu." He has over 20 years of professional Linux experience, having worked for industry leaders such as Hewlett-Packard, Xerox, UPS, FireEye, and Nothing gives him more satisfaction than knowing he has helped thousands of IT professionals level up their careers through his many books and courses.

Covered Topics