Special Variables
$0, $1, $2... and $#
$0 holds the name the script was invoked with, while $1, $2, and so on hold the individual arguments passed to it in order. $# tells you how many positional arguments were supplied, which is useful for validating input before using it.
Warning: set -- alpha beta gamma is used here to simulate command-line arguments inside the script for demonstration.
Example: $0, $1, $2... and $#
#!/bin/bash
set -- alpha beta gamma
echo "Script name: $0"
echo "First arg: $1, second arg: $2"
echo "Total args: $#"
Login to try C/C++/Java/PHP code in the editor
$@ vs $* Unquoted
Unquoted, both $@ and $* expand to all positional parameters separated by spaces and are then subject to word splitting, so they behave identically in that form. The difference only shows up once you quote them.
Example: $@ vs $* Unquoted
#!/bin/bash
set -- one two three
for arg in $@; do
echo "unquoted \$@: $arg"
done
Login to try C/C++/Java/PHP code in the editor
"$@" vs "$*" Quoted
Quoted as "$@", each positional parameter expands as its own separate, fully preserved word (spaces inside an argument stay intact). Quoted as "$*", all parameters are joined into a single string separated by the first character of IFS (a space by default).
Warning: When forwarding arguments to another command, "$@" is almost always the correct choice.
Example: "$@" vs "$*" Quoted
#!/bin/bash
set -- "first arg" "second arg"
echo "Using \"\$@\":"
for arg in "$@"; do
echo " [$arg]"
done
echo "Using \"\$*\": [$*]"
Login to try C/C++/Java/PHP code in the editor
$?, $$, and Other Specials
$? gives the exit status of the most recently completed command, and $$ gives the process ID of the currently running shell itself, which is often used to build unique temporary filenames. These specials are read-only and update automatically as the script runs.
Example: $?, $$, and Other Specials
#!/bin/bash
echo "This script's PID is $$"
true
echo "Exit status after true: $?"
tmpfile="/tmp/scratch_$$.txt"
echo "Would use temp file: $tmpfile"
Login to try C/C++/Java/PHP code in the editor
- Confusing
$@and$*; unquoted they behave the same, but quoted,"$@"expands each argument as a separate word (preserving spaces inside each), while"$*"joins all arguments into one single string. - Assuming
$0is always just the script's filename; it is actually whatever string was used to invoke the script, which can be a relative path, absolute path, or just a name depending on how it was called. - Forgetting
$$is the current shell's own process ID, not the ID of the last background command started (that is$!, a related but different special variable).
$0is the name/path used to invoke the script;$1,$2, ... are the positional arguments passed to it.$#is the count of positional arguments;$@and$*both expand to all of them, but differ when quoted."$@"is almost always what you want when forwarding arguments, since it preserves each argument as a separate word even if it contains spaces.$?is the exit status of the last command;$$is the current process's PID.
Chapter Quiz — Complete all 13 topics to unlock
0/13 topics done
Complete these topics first: