1. Introduction

In Bash scripting, understanding the difference between $* and $@ is crucial for handling command-line arguments correctly. We use both variables to represent the command-line arguments passed to a script or function, but they can behave differently.

In this tutorial, we’ll explore the key distinctions between $* and $@ in Bash.

2. The $* Variable

The $* variable represents each command-line argument as a single string. The arguments are separated by spaces and aren’t joined together.

To illustrate the usage of this variable, let’s create a Bash script named dollarStar.sh:

#!/bin/bash
for arg in $*; do
  echo "$arg"
done

Let’s explain it line by line:

  • for arg in $*; do uses a for loop to iterate over the elements of $*
  • echo “$arg” prints the value of the arg variable to the screen
  • done marks the end of the loop body

We can use chmod +x dollarStar.sh to give the executive permission to dollarStar.sh. Let’s see what happens when we run it:

$ ./dollarStar.sh Journey to the cloud
Journey 
to 
the 
cloud

In the example, Journey to the cloud are the command-line arguments. We see that $* splits them so that each argument becomes a separate string.

In general, we use $* when we want to treat every argument as a single string. This is suitable for string manipulation or passing them to another command.

2.1. Using “$*”

Enclosing the variable $* with double quotes means all arguments will be treated as a single string jointly.

If we replace $* with “$*” in dollarStar.sh and name the new script as dollarStarQuoted.sh:

for arg in "$*"; do
    echo "$arg"
done

and give it the executive permission*,* we’ll get:

$ ./dollarStarQuoted.sh Journey to the cloud
Journey to the cloud

All the arguments are combined into a single word, with spaces between them.

3. The $@ Variable

The variable $@ treats each command-line argument as a separate element in an array.

As an example, let’s create another script (dollarAt.sh):

#!/bin/bash
for arg in $@; do
  echo "$arg"
done

It iterates over the elements of $@. After setting the permissions, we can run it like our first script:

$ ./dollarAt.sh Journey to the cloud
Journey 
to 
the 
cloud

We see that $@ preserves the original structure of the arguments and that we can access them as separate items within the loop.

We use $@ to preserve argument quoting or work with individual arguments within loops or functions.

3.1. Using “$@”

Both $@ and “*$@”* treat each command-line argument separately. If we change $@ to “$@” in dollarAt.sh and name the new script as dollarAtQuoted.sh:

for arg in "$@"; do 
    echo "$arg" 
done

the result will be the same:

$ ./dollarAtQuoted.sh Journey to the cloud  
Journey 
to 
the 
cloud

In most cases, using $@ or “$@” instead of $* is safer and more flexible when working with command-line arguments because they preserve the original argument structure and make it easier to work with individual arguments in our bash script. 

4. Comparison of $* and $@

If we pass quoted command-line arguments like “Journey to” “the cloud” to $* and $@, we get the same results as before:

$ ./dollarStar.sh "Journey to" "the cloud"
Journey 
to 
the 
cloud
./dollarAt.sh "Journey to" "the cloud"
Journey
to
the
cloud

However, passing these quoted arguments to “$@” and “$*” gives different outputs. The quoted variable “$@” treats each quoted sequence of characters as an individual argument, but “$*” treats them as a single entity:

$ ./dollarStarQuoted.sh "Journey to" "the cloud"
Journey to the cloud
./dollarAtQuoted.sh "Journey to" "the cloud"
Journey to
the cloud

5. Conclusion

In this article, we explored the similarities and differences between $* and $@ and their quoted variants. They behave the same way when not quoted: They treat each argument as a separate entity and preserve spaces and special characters within individual arguments. However, their behavior is different if we quote them. While “$@” keeps individual arguments, “$*” treats them as a single entity.