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:
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 -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:
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:
|$0||Name of the script|
|$1||Value of the first argument|
|$2||Value of the second argument|
|$n||Value 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:
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 188.8.131.52
Cool, it works! What about with another domain?
./dns_resolver.sh codefather.tech 184.108.40.206
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 220.127.116.11 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 18.104.22.168 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
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
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
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for Robotics with projects that include Raspberry Pi and Arduino platforms.