Bash Script: Flags usage with arguments examples

If you have any experience on the Linux command line, then you should have run into command flags, which help us modify the behavior of a command that we are executing.

For example, if we execute the ls -l command, the -l part of the command is a flag that we are passing as an argument to ls. This same functionality can be used in a Bash script, allowing us to pass some input to the script through flags when we are executing the script.

Modifying a Bash script’s behavior via runtime options, just like we normally do with command line programs, can be very useful. The Bash shell provides the getopts builtin command, a standard way to achieve this. In this tutorial, you will see how to use flags as arguments when executing a Bash script, through use of the getopts builtin.

In this tutorial you will learn:

  • How to pass arguments to a Bash script via flags
  • How to interpret flag input via getopts
An example of using getopts to read input flags from within a Bash script
An example of using getopts to read input flags from within a Bash script
Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Any Linux distro
Software Bash shell (installed by default)
Other Privileged access to your Linux system as root or via the sudo command.
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

Bash Script: Flags usage with arguments example

Let’s go over a basic example of using getopts in a Bash script. We are not aiming for practicality here, but just a simple script that allows you to easily understand how getopts works.

We will configure our script below to accept command line options -l, -h, and -a.


while getopts 'lha:' OPTION; do
  case "$OPTION" in
      echo "linuxconfig"
      echo "you have supplied the -h option"
      echo "The value provided is $OPTARG"
      echo "script usage: $(basename \$0) [-l] [-h] [-a somevalue]" >&2
      exit 1
shift "$(($OPTIND -1))"

Let’s analyze what we have above. First of all, the getopts commands must be used inside a while loop so all options are parsed. Then immediately after the getopts keyword, we defined the possible options our script will accept. They are l, h and finally a.

What does the colon after this last option means? It is the way we tell getopts that the option requires an argument. Each parsed option will be stored inside the $OPTION variable, while an argument, when present, will become the value of the $OPTARG one.

Each option is managed inside a case statement, with a final ? case that will be matched whenever an option that doesn’t exist will be provided. In that case we will just echo the user the correct script usage and exit with an error code.

Testing our script

First, we are going to call our script providing a non existing option, just to test the case we mentioned above. Let’s give the script executable permissions and then call it:

$ chmod +x && ./ -c

As expected, we will receive a message telling us that the provided option is illegal and then instructions about how to use the script:

$ ./ illegal option -- c
script usage: [-l] [-h] [-a somevalue]

While the script usage string is the one we set to be printed on usage error, the illegal option message above it is automatically generated by getopts and it can be disabled by prefixing the options with a :. Now let’s see what happens when we use the script the way it was meant to:

$ ./ -l

We used the -l option, and the script printed onscreen the string we set in the corresponding case, this is also what happens if we provide the -h option:

$ ./ -h
you have supplied the -h option

Let’s now try to call the script with the -a option. As said above, this option requires an argument, and will fail if the latter is not provided:

$ ./ -a
./ option requires an argument -- a
script usage: [-l] [-h] [-a somevalue]

As expected, the script responded with an error message, reminding us that the option we provided requires an argument:

$ ./ -a tux
The value provided is tux

This time the script responded without error. Notice how the argument we provided, tux is printed because it becomes the value of the $OPTARG variable.

Using getopts, you can provide also more than one option at the time to your script, combining the flags when you launch it. For example, let’s see what happens when we try to call our scripts with both the -l and -h options:

$ ./ -lh
you have supplied the -h option

As we can observe, both the options got processed, in the order we provided them. Of course the options can be given separately, and we can also add the -a option, but always remember to add the required argument:

$ ./ -l -h -a tux_rulez
you have supplied the -h option
The value provided is tux_rulez

The $OPTIND variable

If we take another look at the very trivial script we have written above, we see another instruction at the end of the while loop: shift $(($OPTIND -1)). What is its purpose? Let’s say we call the script this way:

$ ./ -l -h -a hello world

When the script is invoked, the $OPTIND variable is set to 1, and it is incremented each time an option is parsed, until it reaches the last one. Therefore, in this case, it will have a value of 5 when it will reach the last element, which is hello, the mandatory argument required by the -a option.

shift is a shell builtin which moves the positional parameters of the script down a specified number of positions provided to it as a positive number, discarding the related arguments.

The way we launched the script above, the last provided argument, “world”, is not parsed by getopts, which at that point already finished its job.

Now, if we make a shift of the value of $OPTIND - 1 (that is the effective number of the parsed options, 4 in this case) on the positional parameters, what remains are just the arguments that are not options, in this case “world”, that we can access by using the $* variable later in this script.

Closing Thoughts

In this tutorial, we saw how to parge flags used as command line arguments passed to a Bash script. The getopts Bash builtin allows our script to accept command flags, even multiple at a time, much the same way that default commands work on a Linux system. We also learned about the $OPTIND builtin, which is handy in this type of script and allows us to process additional input.

Comments and Discussions
Linux Forum