How can I pass arguments to a Bash script?

In this article, we will create a simple Bash script and show how to pass arguments to it using the Linux command line.

How can you pass arguments to a Bash script?

Arguments passed to a Bash script follow the name of the script in the command line and they are separated from each other by a space. Each argument can be referenced in the script by positional parameters defined by default in Bash ($1, $2, $3, etc…).

Given a domain, we want to know the IP address mapped to it.

You could use a simple command like dig instead of a script, and the point here is to show you how you can pass command line arguments to a Bash script and then execute any logic you want based on those arguments.

So in this example, the Bash script will be extremely simple but this concept applies also if you want to have a complex logic that goes through a sequence of commands based on input arguments.

Passing arguments to a Bash script allows you to use the same script in a more generic way, instead of making it depend on specific values hardcoded in the script.

Let’s get started!

First Version of The Script Without Arguments

In the first version of our script, we simply use the dig command to print the IP address for google.com. In our script, we will execute the following command:

dig +short google.com

So, let’s create our basic Bash script, we will call it dns_resolver.sh. Where .sh is the standard extension for Shell scripts.

To edit the script we can use the vim editor:

vim dns_resolver.sh

Below you can see the content of the script:

#!/bin/bash

dig +short google.com 

What is the meaning of #!/bin/bash ?

It’s called Shebang, something for a different day, for now, you can use it the way it is and remember that it will always be the first line in your Bash scripts.

Executing Your Script

To execute the script use the following command:

./dns_resolver.sh

What happens?

./dns_resolver.sh
-bash: ./dns_resolver.sh: Permission denied 

Why this “Permission denied” error?

ls -al dns_resolver.sh
-rw-r--r--  1 ec2-user  ec2-user  35 16 Feb 13:23 dns_resolver.sh

Because the script doesn’t have executable permissions set, as confirmed by the ls command above.

So, what can we do now? How can we set the executable permissions?

We can use the chmod command to set executable permissions on our script:

chmod +x dns_resolver.sh 
ls -al dns_resolver.sh 
-rwxr-xr-x  1 ec2-user  ec2-user  35 16 Feb 13:23 dns_resolver.sh

The chmod +x command assigns executable permission on our script to the user owner, group owner, and others.

You can see highlighted in bold the executable permissions that have been assigned to the script (identified by the x letter).

Here you can learn other ways to set permissions using chmod.

And now, we try to execute the script again:

./dns_resolver.sh
172.217.169.78 

Bingo!! The script now works as expected and it returns the IP address for google.com.

Difference Between Arguments and Parameters in Bash

Before learning how to pass arguments to a script, I want to clarify the difference between arguments and parameters which could be quite confusing.

Arguments are those that you pass in the command line next to the script name:

./dns_resolver.sh arg1 arg2 arg3

They allow you to implement a generic logic in your script and to assign values to variables used by the script based on the values of arguments provided by the command line.

Parameters refer to variables that arguments are assigned to.

In Bash, they are actually called positional parameters because the value of arguments is assigned to them based on the position of the argument in the command executed via the command line.

The default names of positional parameters in Bash are:

$0, $1, $2, $3, etc...

The following table shows the meaning of the Bash positional parameters:

Parameter nameValue
$0Name of the script
$1Value of the first argument
$2Value of the second argument
$nValue of the nth argument

So the parameters are called positional because the value of the first argument is assigned to the $1 parameter, the value of the second argument to the $2 parameter, and so on.

Using $1 in our Bash Script?

Good, you now know how positional parameters behave.

Now that we have a script that works we want to be able to pass the value google.com via the command line.

This will allow us to have a more flexible script that can handle any domains we want.

So we want to execute the script in the following way:

./dns_resolver.sh google.com

Then the script should read the argument google.com and pass it to the dig command.

To do that we will use the parameter $1 that, as we said before, in Bash has the value of the first argument passed to the script.

So our script becomes:

#!/bin/bash

dig +short $1 

Let’s execute it and see what happens:

./dns_resolver.sh google.com
172.217.169.14 

Cool, it works! What about with another domain?

./dns_resolver.sh codefather.tech
176.58.107.26

It works too!! So, now we have a script that is a lot more powerful than the first version.

And in the same way, we use $1 to read the first argument passed to the script via the command line, we can use $2, $3, $4, etc… for the second, third, and fourth argument…and so on.

For clarity, let’s print the value of $2 and $3 when we execute our script using the echo command:

#!/bin/bash

dig +short $1

echo "The value of the second argument is: $2"
echo "The value of the third argument is: $3"

If I run the script in the same way as before, I get:

./dig.sh codefather.tech
176.58.107.26
The value of the second argument is:
The value of the third argument is:

The second and third arguments are empty because I haven’t provided them via the command line.

Let’s pass some dummy values as second and third arguments:

./dig.sh codefather.tech domain2 domain3
176.58.107.26
The value of the second argument is: domain2
The value of the third argument is: domain3

This time the values of $2 and $3 are printed in the terminal, and if I want I can use them in the logic of my script.

What is $@ is Bash?

Bash provides a special variable called $@, an array that contains all the positional parameters.

Let’s use a for loop to read all the values in $@ when we execute our script:

#!/bin/bash

for ITEM in "$@"
do
    echo $ITEM
done

And the output is:

$ ./dig.sh codefather.tech domain2 domain3
codefather.tech
domain2
domain3

Makes sense?

How to Check the Number of Arguments Passed to a Bash Script

Another thing that can be very useful when you write a script, is checking the number of arguments passed to the script.

You can use this check to make sure the user passes the correct number of arguments.

This can help you prevent errors during the execution of your script caused by missing arguments.

The number of arguments passed to a Bash script is stored in the $# variable.

Let’s update our previous script to also print the number of arguments passed:

#!/bin/bash

echo "The number of arguments passed to the script is: $#"

for ITEM in "$@"
do
    echo $ITEM
done

And the output is:

(base) Jeter:bash claudiosabato$ ./dig.sh codefather.tech domain2 domain3
The number of arguments passed to the script is: 3
codefather.tech
domain2
domain3

Also, an if statement can be used to verify the value of $#:

if [ $# -ne 3 ]; then
    echo "The number of arguments passed is incorrect"
    exit 1
fi

If the number of arguments is incorrect we stop the execution of the script immediately, using the exit command.

How to Check if Bash Arguments Are Empty?

Another way to verify arguments passed is to check if positional parameters are empty.

For example, I can use an if else statement to check if the parameter $2 is empty:

#!/bin/bash

echo "The number of arguments passed to the script is: $#"

if [ "$2" == "" ]; then
    echo "ERROR: The second argument is empty"
fi

And when I run the script, I can see in the output that the second argument is empty:

$ ./dig.sh codefather.tech
The number of arguments passed to the script is: 1
ERROR: The second argument is empty

Conclusion

In this article, we have learned how to create a new Bash script with vim, how to execute it, and how to pass arguments via the command line.

I have also explained:

  • The difference between arguments and positional parameters.
  • How to print all the parameters using $@.
  • The meaning of the $# variable which contains the number of arguments passed to the script.
  • How to check if an argument is empty.

Does it make sense?

What else could you do to improve the DNS resolver script we have created?

Let me know in the comments below! 🙂


Related FREE Course: Decipher Bash Scripting

4 thoughts on “How can I pass arguments to a Bash script?”

Leave a Comment