FUNDAMENTALS A Complete Guide for Beginners
Proper execution of a Bash script depends on the successful parsing of its arguments. After parsing the arguments users need to access those using the correct syntax within the script. Bash allows the manipulation of command line arguments passed to a script. But figuring out how to do this in a Bash script can sometimes be tricky. In this article, I will discuss all the concerns Bash users have about arguments in a script.
Syntax for Passing Arguments to Bash Script
To pass arguments to a Bash script, simply list them after the script’s name when invoking the script from the terminal. For example:
./script.sh arg1 arg2 arg3
Here, arg1, arg2 and arg3 are three arguments passed to the script named script.sh.
How to Access Arguments in Bash Script
There are a couple of ways to access arguments passed to a Bash script. Most Bash users utilize positional parameters to process arguments in a script. Though less popular, the getopts command to access command line arguments is equally handy.
1. Using Positional Parameters
Arguments passed to a script can be accessed using positional parameters like $1, $2, $3, etc. These parameters correspond to the first, second, third and subsequent arguments provided to the script. Look at the example below to understand how it works:
#!/bin/bash
echo "Hello $1. Welcome to LinuxSimply"
The script prints a message in the terminal using the echo command. It uses $1 (first positional parameter) to access the argument provided to the script.
2. Using “getopts” Command
The getopts command with OPTAG environment can process command line options and arguments. One can provide single or multiple arguments under an option using the getopts command. Here is an example of how getopts handle arguments in Bash script:
#!/bin/bash
while getopts "n:i:" opt;
do
case "${opt}" in
n) processname=${OPTARG};;
i) id=${OPTARG};;
esac
done
echo "processname: $processname";
echo "processid: $id";
This Bash script utilizes the getopts command to parse command-line options and arguments. It expects two options: -n, which takes an argument called processname, and -i, which takes an argument called id.
Inside a while loop, it uses a case statement to handle each option. When -n is encountered, it assigns the following argument to the “processname” variable. On the contrary, when -i is encountered, it assigns the following argument to the “id” variable. After parsing the options, it prints out the values of “processname” and “id”.
How to Check the Number of Arguments in Bash Script
Use the special variable $# to check the number of arguments passed to a script. This variable is used for storing the number of command-line arguments. If there is no argument, then the value of $# will be 0. Here is an example:
#!/bin/bash
echo "Total number of arguments: $#"
Executing the script with no argument shows that the total number of arguments is 0. However, when “arg1”, “arg2” and “arg3” are provided the script displays that the number of arguments is 3.
How to Get All the Arguments Passed to a Script
To get all the arguments passed to a script, use the special variables S@ or S*. These two variables contain the array of all input parameters provided to a script. However, the value of these variables may differ depending on whether they are quoted or not.
1. Utilizing $@ to Get All Command Line Arguments
The $@ variable holds all the arguments passed to a script. Therefore, it is used to get all the command line arguments. Here’s how:
#!/bin/bash
echo "Arguments provided to the script: $@"
arg1, arg2 and arg3 are three arguments provided while executing the Bash script. The image confirms that $@ correctly captures and displays all the command-line arguments passed to the script.
Double-quoted (“$@”) and unquoted ($@) may behave differently. “$@” expands to an array of separate strings containing the arguments. On the other hand, $@ splits the input arguments into words separated by space (Or based on the first field of the IFS variable). The difference is visible when you iterate over the input arguments using a for loop:
#!/bin/bash
# Using $@
echo "Using \"\$@\":"
for arg in $@; do
echo "$arg"
done
# Using "$@"
echo "Using \"\$@\":"
for arg in "$@"; do
echo "$arg"
done
This Bash script demonstrates the difference between using $@ and “$@” by iterating over the command-line arguments.
In the first loop, $@
is used without quotes, causing word splitting to occur. By default, words are separated by space. Hence a single argument can be separated into multiple words if it contains space.
In contrast, the second loop uses "$@"
with double quotes, preserving each argument as a separate string. This ensures that arguments containing spaces or special characters are treated as single units.
$@
causes the arguments arg1, “arg 2” and arg3 to split into four different words. Because there is a space in the second argument. However, when quoted “$@”
expands to three different arguments as provided to the script.
2. Utilizing $* to Get All Command Line Arguments
Similar to $@, $* is used to get all the command line arguments.
#!/bin/bash
echo "Arguments provided to the script: $*"
$*
retrieves all the argument three arguments a,b and c provided to the script.
Again, double-quoted and unquoted $* behave differently. “$*” expands to a single string. On the contrary, $* splits into words separated by space (Or based on the first field of the IFS variable). Let’s visualize the difference using a for loop:
#!/bin/bash
# Using "$*"
echo "Using \"\$*\":"
for arg in "$*"; do
echo "$arg"
done
# Using $*
echo "Using \$*:"
for arg in $*; do
echo "$arg"
done
This Bash script illustrates the difference between using “$*” and $* to iterate over command-line arguments.
In the first loop, double-quoted “$*” causes all command-line arguments to be expanded into a single string. Consequently, the loop iterates only once, printing all arguments as a single string. Conversely, in the second loop, $* is used without double quotes, causing word splitting to occur. Hence, any separation by space in the arguments is treated as a separate word, leading to one more iteration of the loop.
What is the Difference Between “$@” and “$*”
The main difference between “$@” and “$” is that “$@” expands to a string for each command line argument. Whereas “$*” expands into a single string with all of the words parsed as arguments. This is easy to understand with the following example:
#!/bin/bash
# Using "$@"
echo "Using \"\$@\":"
i=0
for arg in "$@"; do
echo "$arg"
((i++))
done
echo "Loop runs $i times"
# Using "$*"
echo "Using \"\$*\":"
j=0
for arg in "$*"; do
echo "$arg"
((j++))
done
echo "Loop runs $j times"
In the first for loop the script iterates over command line arguments using “$@”. It initializes a counter i
to track the number of iterations. It proceeds to traverse each argument individually through a for loop, printing each argument and incrementing i
accordingly. Finally, the script outputs the total number of iterations, reflecting the count of command-line arguments.
In the second portion, it program uses “$*” to iterate over arguments. This time it initializes a counter j
. Again the script attempts to print each argument stored in “$*” while incrementing j
in each iteration.
Here, the arguments provided to the script are arg1, “arg 2” and arg3. "$@"
expands to an array of three elements each containing the arguments provided to the script. Hence, when iterating over “$@”, the loop runs three times, each time accessing one of the arguments.
On the other hand, "$*"
expands to a single string containing all the arguments concatenated together. Therefore, when iterating over “$*”, the loop runs only once since there is only one element in the array.
How to Shift Command Line Arguments in Bash Script
Shifting command-line arguments in a Bash script allows you to access subsequent arguments by adjusting their positional index. The shift command is used for this purpose. After calling shift, the $1 will be the value of $2, $2 will be the value of $3 and so on. The following script demonstrates the shifting of command line arguments:
#!/bin/bash
echo "First Argument: $1"
shift
echo "Second Argument: $1"
After the shift command, $1 retrieves “arg2” which is the second argument provided to the script.
Moreover, one can provide a number as an argument to the shift command. shift n (n is the number) causes the positional parameters to be shifted left by n positions. For instance, shift 3 causes the fourth argument to become accessible by $1, and the fifth argument becomes accessible by $2 and so on.
#!/bin/bash
echo "First Argument: $1"
shift 3
echo "Fourth Argument: $1"
After shifting the command line arguments by 3, $1 can retrieve the fourth argument which is 14.
How to Change Command Line Arguments in Bash
In a Bash script, you can change command-line arguments by assigning them to variables within the script. This approach allows you to manipulate the arguments without directly modifying them. Here’s an example:
#!/bin/bash
# Assign command-line arguments to variables
arg1=$1
arg2=$2
# Modify the first argument
arg1="Nan"
echo "Modified first argument: $arg1"
This script assigns the first two command-line arguments to variables arg1 and arg2. It then modifies the value of “arg1” by assigning it the string “Nan”. Finally, it prints the modified value of “arg1”.
The first argument provided to the script is 75. But after taking it in a variable the script modifies the value of the variable to “Nan”.
The set command provides a direct way to modify the command line arguments. The following script shows how the set command can be used to update the arguments:
#!/bin/bash
# Update the arguments as required
set -- "${@:1:2}" "Nan" "${@:4}"
# Display the updated arguments
echo "Updated arguments: $@"
echo "Third argument: $3"
This script updates the arguments passed to it by replacing the third argument with “Nan” while preserving the first two arguments and those from the fourth onwards. It achieves this by using the set --
command to redefine the entire argument list. The ${@:1:2}
syntax selects the first two arguments, and ${@:4}
selects all arguments from the fourth position onwards, effectively excluding the third argument. “Nan” in the middle sets the new value of the third argument.
Finally, the script echoes the updated arguments using $@ and displays the third argument separately using $3.
Practice Tasks on Bash Script Argument
Write a bash script named myscript.sh that takes 10 arguments as follows:
./myscript.sh a b c "arg 3" x 10 15 32 y z
- Echo the first and last argument using positional parameter?
- Change the fifth argument to “Null” and access it using positional parameter $5?
- Shift the arguments so that you can access the last argument using the first positional parameter ($1)?
- Print all the arguments using $@ and $*?
- Use a for loop to iterate over “$@” and “$*”. Determine how many times the loop runs?
Conclusion
In conclusion, Bash provides various methods for accessing and modifying arguments passed to a script. Positional parameters serve as the default choice for this purpose. Additionally, special variables such as “$@” or “$*” allow users to examine all command-line arguments. Furthermore, the process of shifting command-line arguments enables users to alter the positional index of arguments. Finally, the set built-in allows direct modification of command-line arguments within the script
People Also Ask
What is the meaning of $0 in the Bash shell?
The special variable $0 refers to the name of the script that is currently being executed. For example, if you run a script named myscript.sh using the command ./myscript.sh, then within the script, the value of $0 would be myscript.sh.
How to access command line arguments after the first 9 positional parameters?
To access command line arguments beyond the first 9 positional parameters in a bash script, you can use ${10}, ${11}, and so on. This allows you to access arguments beyond the positional parameters 0 through 9. Don’t use $10 without curly braces. This will expand to the first positional parameter($1) and then add the literal 0 after the expansion.
Which one should I prefer between “$@” and “$*” to get all the arguments?
To get all command line arguments in a bash script, “$@” is generally preferred over “$*”. Because “$@” treats each command-line argument as a separate entity. While “$*” expands to a single string containing all the arguments.
How to pass a file as an argument to a bash script?
To pass a file as an argument to a Bash script, you would typically provide the filename as an argument when running the script from the command line. Here’s how you can do it:
./script.sh filename.txt
To access the contents of the file inside the script use the corresponding positional parameter:
data=$1
Why “argument list too long” error occur in Bash?
The “argument list too long” error occurs in Bash when someone attempts to pass a large number of arguments to a bash script or a command that exceeds the predefined argument limit of the system. The limit is typically around 100,000 arguments. This limit is imposed to prevent memory overflow and ensure system stability.
Related Articles
- How to Check Number of Arguments in Bash? [3 Methods]
- How to Use First Argument in Bash Script [5 Cases]
- How to Get Argument in Bash? [4 Methods]
- How to Pass Arguments to Bash Script? [5 Methods]
- How to Parse Optional Arguments in Bash Script [2 Ways]
- How to Pass Array as an Argument in Bash Function? [3 Ways]
- How to Set Default Argument in Bash [2 Methods]
- How to Use OPTARG in Bash [3 Practical Examples]
- How to Use “getopts” in Bash [Complete Guide]
- [Solved] “bash: Argument list too long” Error
<< Go Back to Bash Functions | Bash Scripting Tutorial