Keywords: Bash scripting | command-line arguments | parameter expansion
Abstract: This article provides an in-depth examination of the fundamental differences between $@ and $* special parameters in Bash scripting. It explores how quoting affects parameter expansion behavior through practical code examples, covering scenarios with spaced arguments, loop iterations, and array operations. The discussion includes IFS variable implications and guidelines for selecting appropriate parameter expansion methods to ensure script robustness.
Introduction
In Bash script programming, command-line argument handling is a fundamental and critical task. Many developers encounter the $@ and $* special parameters that appear similar at first glance. While both can access all positional parameters, they exhibit important differences in practical usage, particularly in scenarios involving quotes and parameter separation.
Basic Concepts and Surface Similarity
Let's first observe the similar behavior of $@ and $* when unquoted:
#!/bin/bash
echo "Using $*:" $*
echo "Using $@:" $@
When executing bash script.sh arg1 arg2, both produce identical output:
Using $*: arg1 arg2
Using $@: arg1 arg2
This surface consistency often leads beginners to believe the two are interchangeable.
Critical Differences Revealed by Quoting
The true distinctions emerge when parameters are quoted. Consider arguments containing spaces:
set -- "arg 1" "arg 2" "arg 3"
Comparison of Unquoted Expansion
When used without quotes, both undergo word splitting:
for word in $*; do echo "$word"; done
# Output:
# arg
# 1
# arg
# 2
# arg
# 3
for word in $@; do echo "$word"; done
# Output:
# arg
# 1
# arg
# 2
# arg
# 3
Significant Differences in Quoted Expansion
With quoting applied, the differences become apparent:
for word in "$*"; do echo "$word"; done
# Output:
# arg 1 arg 2 arg 3
for word in "$@"; do echo "$word"; done
# Output:
# arg 1
# arg 2
# arg 3
"$*" combines all parameters into a single string, while "$@" maintains each parameter's individuality.
Impact of the IFS Variable
The behavior of $* is influenced by the IFS (Internal Field Separator) variable. When using "$*", parameters are joined using the first character of IFS:
IFS=:
echo "$*"
# Output: arg 1:arg 2:arg 3
Practical Application Scenarios
Best Practices for Argument Passing
When needing to pass arguments verbatim to other commands, "$@" is typically the correct choice:
wrapper_command() {
# Correct: preserves argument boundaries
some_command "$@"
}
wrapper_command "file name with spaces" "another arg"
Suitable Scenarios for String Processing
"$*" is more appropriate when all parameters need to be treated as a single string:
log_message() {
local message="$*"
echo "$(date): $message" >> /var/log/myapp.log
}
log_message User login failed for user "john doe"
Common Pitfalls and Solutions
Quoting Nesting Issues
Proper quoting is crucial in complex scripts:
# Incorrect example
for arg in $@; do
some_command $arg # Spaces in arguments cause issues
done
# Correct approach
for arg in "$@"; do
some_command "$arg" # Maintains argument integrity
done
Default Iteration Behavior
Bash provides a simplified iteration syntax that behaves identically to "$@":
for word; do # Equivalent to for word in "$@"; do
echo "$word"
done
Summary and Recommendations
Understanding the differences between $@ and $* is essential for writing robust Bash scripts. Key recommendations include:
- Prefer
"$@"in most cases to preserve original argument boundaries - Use
"$*"only when needing to combine parameters into a single string - Always quote variable expansions unless there's explicit reason not to
- Understand how
IFSaffects$*behavior - Leverage Bash's simplified syntax
for word;for argument iteration
By mastering these concepts, developers can create more reliable and maintainable Bash scripts that properly handle various command-line argument scenarios.