Table of contents
1.
Introduction
2.
Passing Arguments
2.1.
Argument List
2.2.
Flags
3.
Accessing Arguments Inside Bash Script
3.1.
Positional 
3.2.
Flags
3.3.
Looping
3.4.
Shift Operator
4.
Frequently Asked Questions
4.1.
What happens when a value for a flag is required but we don't provide one?
4.2.
What happens if we provide a flag that wasn't asked for?
4.3.
Can we have flags that are more than one letter long?
5.
Conclusion
Last Updated: Mar 27, 2024
Hard

Shell Scripting - Pass Arguments to a Bash-Script

Author Satvik Gupta
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Linux is an open-source kernel for operating systems. It is widely used in operating systems such as Ubuntu, Debian, etc. One of the unique features of Linux is that it allows the user to have a higher degree of control over the machine. We can execute and program many things into our computer using simple commands.

Shell Scripting - Pass Argument to Bash Script

Bash stands for Bourne Again Shell. It is a command language that was written by Brian Fox, and it is a replacement for the Bourne Shell. It is used as the default shell in many Linux distributions. It processes commands written by the user and performs tasks according to them. We can write bash scripts that Linux operating system can execute. Virtually any task we need to do in Linux can be accomplished using bash scripts, such as handling files, running processes, etc. 

In this article, we will see how to pass arguments to a bash script and how to access those arguments inside the bash script.

Passing Arguments

A script is a simple program that we are running. As with any program, a script also needs inputs. For example, if we write a script to connect to a website to let us know if we are receiving a response, the URL of the website will be an input to this script. In Bash, and most other shells, inputs are passed to the script in the form of arguments.
We can pass arguments to a bash script in multiple ways. Let's look at some of them. 

Argument List

This is the simplest way to pass arguments. We simply write each argument separated by space while running the script. For e.g., if we are passing 2 arguments to a script named "demo.sh", we can write:

sh demo.sh hello 100


Here the two arguments passed are hello and 100.

Note that if one of the arguments contains spaces, we must enclose them in single or double quotes.

sh demo.sh "hello world" 100
sh demo.sh 'hello world' 100


If there are arguments that need to be evaluated, we need to enter them in double quotes. For e.g., if we need to pass the $HOME directory as an argument, we need to do it like this:

sh demo.sh "$HOME" 100

 

Special characters such as $ and * need to be escaped with a \

sh demo.sh \$ 100

Flags

Flags are the most common way to pass arguments. Flags are usually single letters, preceded by a dash or a hyphen. When passing arguments as flags, we first write the name of the flag, then its argument after a space. 

For e.g., if a script takes a username argument with flag -u, and an age argument with flag -a, we can write it as:

bash test.sh -u NinjaUser -a 17
Arguments as Flags

Accessing Arguments Inside Bash Script

When we are writing a bash script, we will need to access the values that the user has entered as parameters. Let us see the different ways to do this. 

Positional 

When we receive arguments inside a bash script, they are in the same order that the user wrote them in. So, we can simply access them by their index. The indices start from 1. To access the first argument, we can write $1, for the second we can write $2, and so on. 

So, we can write a script as:

Script to get positional arguments

And run it as:

Output of script for positional parameters

Thus we see that we get the desired output. Here the first argument is Bruce Wayne and the second argument is 100.

Flags

Parsing the arguments from flags is slightly more complicated. We use the getopts function to help us do this. getopts function is used to parse the arguments passed to a bash script. It makes it easier to use the arguments the user has entered directly, without having to parse the text ourselves. 

Let us understand it through an example:

The getopts function is used like this:

while getopts u:a: var
do 
case $var in 
u) username="$OPTARG"
a) age="$OPTARG"
esac
done


Let us understand this:

The string written after the keyword getopts (u:a:) in our case, is the optstring. In this, we specify the flags that we are looking for.

Flags can be of two types - the first type is the flag that requires an argument with it. For example, the -u flag is used to specify the username. It requires the value of the username (such as NinjaUser) as an argument. Arguments of flags are provided after a space. 

For e.g, the command

bash demo.sh -u NinjaUser


Will run the demo.sh script. It will pass the -u flag, with the argument NinjaUser (we will see example runs later). When getopts comes across a flag that has an argument, it puts the value of the argument in the variable OPTARG. We can then access it from there.

The second type of flag does not have any argument associated with it. It is simply passed to indicate the presence of that flag. For example, the -v flag (standing for verbose) tells the script to output details related to the task it is performing, while it is running. It does not have an argument associated with it, the presence of the -v flag is enough to specify that the output should be verbose.

When we are writing the flags in the optstring, both types of flags are written in different ways. 

For the flags that have arguments, we add a colon (:) after the flag character. For flags without arguments, we do not add a colon. For e.g., if our demo.sh script had a -v flag, we could write our optstring as:

vu:a:


We have already seen what OPTARG does. There is also another variable, called OPTIND. This stands for option index. It starts at 1, and getopts increases it by 1 with each iteration of the while loop.

Let's try this out using a script.

username="u"
age="a"
verbose=0
while getopts vu:a: var
do
        case $var in
        u) username=$OPTARG;;
        a) age=$OPTARG;;
        v) verbose=1;;
        esac
done

if [ $verbose == 1 ]; then echo "Printing the output using verbose flag"
fi

echo "Hello Ninja $username";
echo "Your age is $age";


The output will be:

Output of script for flags, without verbose flag

(Without Verbose Flag)

Output of script with flag parameters, with verbose flag.

(With Verbose Flag)

We can see everything works as it is supposed to.

Looping

Sometimes we don't know the number of arguments in a script, so the above techniques won't work. Here, we will have to manually loop through all the arguments and access them.

The variable $@ contains the entire input parameters. So, we can loop through this. 

Suppose we wish to print the lengths of a list of strings. We would write a script like this:

for string in $@
do
echo "$string has length ${#string}"
done


Here, the #string command gives us the length of the variable string. Let's try running it.

Output of script using looping to parse parameters

Shift Operator

We can also handle unknown length inputs using the shift operator. The shift command in bash shifts the position of the command line arguments. So, if we do shift 2, the index of the third argument will now be 1, that of the fourth argument will be 2, and so on. 

Let's write the same above script using this format. 

i=1;
len=$#; #this gives the total number of arguments passed to the script
while [ $i -le $len ]
do
        echo "$1 has length ${#1}";
        i=$((i+1));
        shift 1;
done


The output will be:

Output of script using shift operator to parse parameters.

We get our desired output.

 

Read Also -  Difference between argument and parameter

Frequently Asked Questions

What happens when a value for a flag is required but we don't provide one?

If a flag requires a value, but the user doesn't provide one while calling, bash will print an error. However, it won't stop the rest of the script from executing. If we wish to suppress the errors, we can add a colon (:) to the front of our optstring.

What happens if we provide a flag that wasn't asked for?

Bash will print an error message, telling the user that they have provided an ille.g.al flag. However, it won't stop the script from executing. The rest of the script will execute as is. 

Can we have flags that are more than one letter long?

This might technically be possible but it is not recommended to do so, as it is against the standard practice. The standard way to have long flags is to prefix them with -- instead of a single -. To parse -- options, we will have to use some other function as getops does not support parsing it.

Conclusion

This blog has explored how to pass arguments to a shell script and the various methods to parse an argument inside a bash script. We have looked at the getops function also in detail.

We hope you leave this article with a broader knowledge of Shells, Bash, and shell scripting. We recommend that you explore our different articles on these topics as well, such as:

Introduction to Linux Shell & Scripting Shell

Shell Scripting Interview Questions

Shell Scripting Arithmetic Operations
 

You can practice questions on various problems on Coding Ninjas Studio, attempt mock tests. You can also go through interview experiences, interview bundle, go along guided paths for preparations, and a lot more!

Keep coding, keep reading Ninjas. 

Live masterclass