Fetching latest headlinesโ€ฆ
Understanding `$@`, `$*`, `"$@"`, and `"$*"` in Shell Scripts
NORTH AMERICA
๐Ÿ‡บ๐Ÿ‡ธ United Statesโ€ขApril 17, 2026

Understanding `$@`, `$*`, `"$@"`, and `"$*"` in Shell Scripts

0 views0 likes0 comments
Originally published byDev.to

When working with shell scripts, handling command-line arguments correctly is critical. Variables like $@ and $* are commonly used to access all positional parametersโ€”but their behavior changes significantly depending on whether they are quoted.

This subtle distinction is a frequent source of bugs. In this article, weโ€™ll break down exactly how each form behaves, with concrete examples.

Positional Parameters: A Quick Refresher

Consider the following script invocation:

./script.sh foo bar "baz qux"

The positional parameters are:

  • $1 โ†’ foo
  • $2 โ†’ bar
  • $3 โ†’ baz qux

To refer to all arguments, we use $@ or $*.

Summary Table

Expression Meaning Behavior
$@ All arguments Word-split into separate tokens
$* All arguments Word-split into separate tokens
"$@" All arguments Preserves each argument as a separate item
"$*" All arguments Joins all arguments into a single string

$@ and $* (Unquoted)

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

Behavior

Without quotes, both $@ and $* behave almost identically:

  • They expand to all arguments
  • Then undergo word splitting based on whitespace

Problem

./script.sh "hello world"

This will be treated as:

  • hello
  • world

The original argument structure is lost, which can lead to incorrect behavior.

๐Ÿ‘‰ In practice, unquoted $@ and $* are rarely appropriate.

"$@": The Safe Default

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

Behavior

  • Each argument is preserved as a distinct element
  • Whitespace inside arguments is retained

Example

./script.sh foo "bar baz"

Output:

foo
bar baz

Key Properties

  • Maintains the original number of arguments
  • Preserves boundaries between arguments
  • Safe for filenames and arbitrary input

๐Ÿ‘‰ This is the form you should use in almost all cases.

"$*": Single String Expansion

echo "$*"

Behavior

  • All arguments are concatenated into one string
  • Separated by the first character of IFS (space by default)

Example

./script.sh foo "bar baz"

Output:

foo bar baz

Caveats

  • Argument boundaries are lost
  • Not suitable for iteration or per-argument processing

๐Ÿ‘‰ Useful primarily for logging or display purposes.

Visual Comparison

Given:

./script.sh A "B C" D
Expression Result
$@ A B C D
$* A B C D
"$@" "A" "B C" "D"
"$*" "A B C D"

Common Pitfall

โŒ Incorrect

for arg in $@; do
  cp "$arg" /dest/
done

If an argument contains spaces, it will be split incorrectly.

โœ… Correct

for arg in "$@"; do
  cp "$arg" /dest/
done

This preserves each argument exactly as passed.

Practical Guidelines

  • Use "$@" when passing or iterating over arguments
  • Avoid unquoted $@ and $* unless you explicitly want word splitting
  • Use "$*" only when you intentionally need a single combined string

Why This Difference Exists

The distinction arises from how the shell performs:

  • Parameter expansion
  • Word splitting
  • Quote removal

Notably, "$@" is a special case: it expands to multiple quoted strings, preserving each positional parameter individually. This behavior is unique and not shared by other expansions.

Conclusion

  • "$@" is the safest and most predictable way to handle arguments
  • $@ and $* (unquoted) can break argument boundaries
  • "$*" collapses everything into a single string

If you follow one rule, make it this:

Always use "$@" unless you have a specific reason not to.

Comments (0)

Sign in to join the discussion

Be the first to comment!