Bash Scripting
  • scripting list
  • How to Make Bash Script Executable Using Chmod
  • Shell Script to Check Linux Server Health
  • How to Concatenate String Variables in Bash [Join Strings]
  • How to Do Bash Variable Substitution (Parameter Substitution)
  • Bash Parameter Expansion with Cheat Sheet
  • Bash getopts with Examples
  • How to Pass all Arguments in Bash Scripting
  • Bash Function Return Value
  • Bash Loop Through Lines in a File
  • Bash readarray with Examples
  • Bash let with Examples
  • Bash expr with Examples
  • Bash read password
  • Bash for Loop Range Variable
  • Bash Arrays Explained
  • Ways to Find Bash Array Length
  • Bash Split String by Delimiter
  • Bash if Options
  • Bash If Statements for String Comparison
  • Debugging Techniques for Bash Scripts
  • Determining if a Bash String is Empty
  • Bash if Statement with Multiple Conditions
  • Meaning of Shebang in Bash Scripts
  • How to Comment Code in Bash Script
  • How to Read CSV File in Bash
  • Bash Scripting: How to Check if File Exists
  • Bash If Else Statements: Examples and Syntax
  • Bash Scripting: How to Check if Directory Exists
  • Bash eval Command with Examples
  • How to Use Sleep Command in Bash Scripting
  • Bash Associative Arrays with Examples
  • Bash Script for Counting Lines in a File
  • How to Use While Loop in Bash for Efficient Scripting
  • Bash basename Command with Examples
  • How to Create Multiline Strings in Bash
  • How to Use Bash if With && Operator
  • 50 Bash Script Examples to Kickstart Your Learning
  • Case statement in Bash Shell Scripting
  • Trimming White Space in Bash
  • How to Extract Filename from Absolute Path in Bash
  • How to Get Directory Path in Bash
  • Extract Extension from File Path in Bash
  • Extract Filename without Extension from Full Path in Bash
  • Bash for Each File in a Directory
  • Bash for Loop with Array
  • Bash Continue – Using with for Loop
  • Bash Backticks vs Dollar Parentheses $()
  • How to Assign Variable in Bash
  • How to Assign Variable in Bash
  • Bash Division Explained
  • Bash Modulo (Division Remainder)
  • Bash While Read Line by Line
  • Bash shift Command
  • Bash Looping Through Array of Strings
  • Bash read Command with Examples
  • Bash Check Empty Array
  • Using Bash For Loops to Iterate Over a List of Strings
  • Bash Break – Using with For Loop
  • How to Use seq With for Loop in Bash
  • How to Use $@ in Bash Scripting
  • Get the Current Script Directory in Bash
Powered by GitBook
On this page
  • 1. Introduction
  • 2. What is Bash $@?
  • 3. Difference between $@ and $*
  • 4. Using “$@” Variable in Bash
  • 5. Example Script

How to Use $@ in Bash Scripting

PreviousHow to Use seq With for Loop in BashNextGet the Current Script Directory in Bash

Last updated 1 year ago

1. Introduction

There are certain special variables that you will come across only in Bash. These variables might appear challenging at first. But, understanding how Bash uses these combinations of characters will help you move from an average Linux user to an experienced one.

In this guide, we learn about $@ special variable and how it is useful in Bash. We will see how it differs from $* variable.

2. What is Bash $@?

$@ is an extremely simple yet powerful in Bash. Bash uses it to ease the passing and handling of positional parameters whether be it scripts or functions. Bash expands into the full list of positional arguments $1 $2 $3 … $n. It preserves the argument count through the expansion.

3. Difference between $@ and $*

Without the use of double quotes, both $@ and $* have the same effect. All positional parameters from $1 to the last one used are expanded without any special handling.

When the $* parameter is double quoted, it expands to as:

"$1s$2s$3s……..$N" 

's' is the first character of IFS. If IFS is unset, the parameters get separated by spaces. When IFS becomes null, the parameters join without the intervening separators.

But when the $@ special parameter is wrapped with double quotes, it is equivalent to:

"$1" "$2" "$3"  ….. "$N"

This ensures all the positional parameters are the same as they were set initially and passed to the script or function. If we want to re-use these positional parameters to call another program, we should use double quoted "$@".

Now, let us practically interpret this with an example:

set -- "arg  1" "arg  2" "arg  3"

echo 1. 'With $*'
for word in $*; do echo "$word"; done

echo '2. With $@'
for word in $@; do echo "$word"; done

echo '3. With "$*"'
for word in "$*"; do echo "$word"; done

echo '4. With "$@"'
for word in "$@"; do echo "$word"; done

In this example we have considered four cases:

In the first two cases, the output will be as:

arg 1 arg 2 arg 3

This is because every argument, separated by a space, is considered a separate word.

The third case outputs the following:

arg  1 arg  2 arg  3

This is because "$*" considers all the positional parameters as a single word.

In the final case, we get:

arg  1
arg  2
arg  3

This is because "$@" considers all the positional parameters as separate strings.

Overview Table

Assuming "s” is the first character of the Input Field Separator, we can generalize the results of $* and $@ with and without the quotes as follows:

S_no
Syntax
Result

1

$*

$1 $2 $3 … ${N}

2

$@

$1 $2 $3 … ${N}

3

"$*"

"$1s$2s$3s…s${N}"

4

"$@"

"$1" "$2" "$3" … "${N}"

4. Using “$@” Variable in Bash

From passing all the arguments to other commands, scripts, and functions to substring expansion, we can use the $@ notation. In this section, we will take a look at how to use this special symbol in Bash.

4.1 Accessing all arguments

Bash uses $@ to expand the parameters passed to the script. It begins with the first parameter. If we enclose in double quotes "$@", each parameter is expanded to a separate word. "$@" is equivalent to "$1" "$2" ... "$n".

Example:

#!/bin/bashecho Parameters are: "$@"

Let us save this as mySampleScript1.sh and run it as

./mySampleScript1.sh one two three

$@ is a special shell variable which expands to a list of all arguments. As we have passed 3 parameters to this script, we get to see those 3 parameters on the screen.

4.2 Utilizing $@ within Loops

Example:

#!/bin/bashfor arg in "$@"do echo $argdone

Run this script:

./mySampleScript2.sh one two three

To iterate over the command-line arguments, we are using $@ in a for loop. Then we print one argument at a time on the screen. One important thing to note is the symbol $@. It needs to be surrounded by double quotes. This way Bash handles every argument as a separate word.

4.3 Passing arguments to another command

The $@ symbol also helps to pass command-line arguments to other commands in Bash. It expands to all the command-line arguments passed to the current script when dealing with $@ as an argument to another command.

Example:

#!/bin/bash key=$1shiftgrep $key $@

Let us execute this script as follows:

./mySampleScript3.sh sample *.txt

$@ expands to all the remaining command-line arguments. They are effectively treated as filenames (*.txt) to be searched for the provided keyword. Hence, our script will search for the keyword "sample" in all txt files.

4.4 Substring expansion on parameters

The basic form of parameter expansion is ${parameter}. The fundamental form of substring expansion is:

${parameter:offset:length}

Let us understand this with examples:

Example 1:

set -- 1 2 3 4 5 6 7 8 9echo ${@:5:0}echo ${@:5:2}

It expands till the length of characters of the value of parameter starting at the character specified by offset. The variables length and offset can be arithmetic expressions as well.

In the first case, we have passed the length as zero, hence we do not get any visible output. Similarly,we are picking 2 characters beginning with the 5th position.

Example 2:

set -- 1 2 3 4 5 6 7 8 9echo ${@:7}

If the length variable is ignored, it expands the parameter at the character specified by the offset. It extends till the end.

Example 3:

set -- 1 2 3 4 5 6 7 8 9echo ${@:5: -2}

We get the expected expansion error when the length is less than zero.

Example 4:

set -- 1 2 3 4 5 6 7 8 9echo ${@: -3:2}

A negative offset is taken relative to one greater than the greatest positional parameter. This way an offset of -1 evaluates to the last positional parameter. It is interpreted from the end of the value of parameter. The expansion is the characters between the offset till the length. A negative offset has to be separated from the colon by at least one space.

We have an offset of -3 which corresponds to the number 7. And we pick two characters from there, thus getting 7 and 8 on the screen.

Example 5:

set -- 1 2 3 4 5 6 7 8 9echo ${@:0}echo ${@:0:2}

This example illustrates that the offset at zeroth position is bash. In the first case, we get the output as -bash followed by the 9 digits since we haven’t specified the length. In the next case, we have restricted it to pull out the first two positions by specifying the length as 2. This gave us the result as -bash 1.

4.5 Handling quoting and spaces

When the parameter is quoted, Bash hands over all arguments the way it received them, even if there are unnecessary spaces. Let us see how the outcome differs with and without the use of the quotes.

Example:

#!/bin/bashecho Parameters without quotes are: $@echo Parameters with quotes are: "$@"

Let us save this as mySampleScript4.sh and run it as:

./mySampleScript4.sh "one     two                 three"

In the first case, since we haven’t wrapped the $@ with double quotes, we are losing the extra spaces between the positional arguments passed to the script. In the other case, quoting with double quotes ensures that those spacings are retained.

4.6 Functions and $@

$@ is employed to pass arguments between functions.

Let us understand this with an example. We have two functions f1 and f2. Both accept positional parameters. If f1 calls f2, then we can pass all the arguments from f1 to f2 by simply using:

f2 "$@" 

This will expand to all the positional parameters passed to function1. Let us write a simple script to understand it even better.

#!/bin/bash #function 2f2(){ echo "Bye, $1 $2"} #function 1f1(){ echo "Hello, $1 $2" #calling function 2 inside function 1 f2 "$@"} #triggering f1f1 "Roger" "Federer"

We have 2 functions where f2 is being called by f1. We run the script by calling f1 with 2 arguments. Hence it will echo the hello message. After this, it will call f2 with the same parameters that it consumed. This will result in printing of the bye message.

5. Example Script

We will take a real-world problem where the user provides a list of files and the script generates backup of those files by appending the timestamp.

Example:

#!/bin/bash usage(){ echo "Usage: ./backup.sh <file1> [<file2> ... <fileN>]"} if [ "$#" -lt 1 ]thenecho "No file specified." usageexit 1fi for file in "$@"do if [ ! -f "$file" ] then echo "[ERROR] File $file doesn't exist" continue else currentDate=`date +%d-%m-%y` currentTime=`date +%H-%M` cp $file ${file}_${currentDate}_${currentTime} RC=${?} if [[ ${RC} -eq 0 ]] then echo "Copied $file to ${file}_${currentDate}_${currentTime}" fi fi done

1. The usage function displays how to run the script.

2. We count the number of arguments available to the script. No arguments are supplied if it is less than 1. In this case, we call the usage method and terminate the script.

3. If the arguments are more than 1, then we read all the arguments using "$@" one by one using the for loop.

4. For every entry, we check if the specified input is a file or not. If it is not a file, we display an error message and jump to the next iteration using the continue statement.

5. If it is a file, we extract the current date and time from the Bash date command.

6. We then create a backup copy the file with the name: file_<dateDD-MM-YYYY>_<timeHH-MM>

7. We then verify the exit status of the cp command. If its numerical value is zero, it indicates that the command succeeded.

8. We finally display the successful copy message.

9. We repeat this for the next entry in the for loop.

We can use the $@ notation within the loops to refer to every command-line one by one.

When we run mySampleScript3.sh, the first command-line argument $1 gets assigned to the key variable. The then omits the first argument. $key and $@ are the arguments to the grep command.

special parameter
argument passed to a script
shift command
script will search for the keyword "sample" in all txt files
passed 3 parameters to the script
usage of ${@:5:2} extracts the fifth and sixth command-line arguments and prints them. However, the line ${@:5:0} will not produce any output.
output of the script will be 7 8, which corresponds to the third-to-last and second-to-last command-line arguments.
script output using $@ in a for loop
The output demonstrates the differences between $*, $@, "$*", and "$@" when iterating over command-line arguments in a shell script
the output of the script will be 7 8 9, which corresponds to the command-line arguments starting from the seventh position onward.
showing error when the length is less than zero
The first line shows the command-line parameters without quotes, and the second line shows the command-line parameters with quotes
offset at zeroth position is bash
The execution flow of the script, showing the greeting message from f1 and the farewell message from f2, both using the provided arguments.
examples script - for loop iterates over each command-line argument ($@), which represents the files to be backed up