Propagate all arguments in a Bash shell script
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
A shell wrapper often needs to forward every argument it receives to another command. That sounds simple, but Bash has several similar-looking expansions, and only one of them is correct in most real scripts.
The safe default is "$@". It preserves argument boundaries exactly, including spaces, quotes that have already been parsed by the shell, and empty arguments. Most propagation bugs come from using $@, $*, or an unquoted variable instead.
Why "$@" Is The Right Tool
Bash exposes positional parameters as $1, $2, and so on. For "all arguments," the two special forms people compare are $@ and $*.
The important rule is what happens when they are quoted:
- '
"$@"expands to separate arguments' - '
"$*"expands to one single string'
That difference is why wrappers almost always want "$@".
If the script is called like this:
then "$@" preserves all three arguments exactly, including the empty one.
Forward Arguments To Another Command
The canonical wrapper pattern is:
Using exec is optional, but it is common when the wrapper's only job is to hand off control to another command. It replaces the shell process with the target command instead of starting an extra child process.
If you need to add fixed options before forwarding the user-provided ones, keep the fixed options separate and still forward the original arguments with "$@":
This is a common pattern for small command wrappers that enforce defaults without destroying flexibility.
When You Need To Inspect Or Modify Arguments
Sometimes you want to check the first argument, strip an option, or add a flag. Bash makes this easy as long as you continue to preserve argument boundaries.
Here shift removes the first positional parameter, and "$@" forwards the remaining ones correctly. Notice that the debug message uses $* only for display. That is fine because it is being printed, not used as command input.
Arrays Are Better Than Building Strings
If you need to construct a command dynamically, do it with an array rather than string concatenation:
This is the safe Bash way to build commands. Concatenating a string such as cmd="python3 tool.py $*" and then executing it later invites quoting bugs and sometimes command-injection bugs.
Common Pitfalls
- Using
$@without quotes, which lets the shell split and glob arguments again. - Using
"$*", which collapses all arguments into one string. - Printing debug output with one expansion and assuming it behaves the same way when used as a command.
- Building commands with string concatenation instead of arrays.
- Forgetting that
shiftchanges the positional parameters seen by the rest of the script.
Summary
- Use
"$@"when you want to forward all original arguments safely. - '
"$@"preserves each argument as a separate value.' - '
"$*"is usually wrong for propagation because it becomes one string.' - Use arrays when you need to build a command dynamically.
- Treat argument forwarding as a quoting problem first, not a syntax shortcut.
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.