The variables I use in almost every Bash script are $0, $1–$9, $#, $@, $?, $$, and IFS. These provide the script name, positional arguments, argument count, all arguments, exit status, process ID, and field separator—together they handle input, error checking, and output parsing in most scripts.
Why These Variables Matter
Every Bash script, no matter how simple, needs to know three things: what arguments were passed, whether the previous command succeeded, and how to separate data. The variables listed above answer those needs directly. $0 gives the script’s own name, useful for usage messages. $1 through $9 are the first nine positional parameters. $# tells you how many arguments were supplied, so you can validate input. $@ expands to all arguments, preserving each as a separate word—essential when passing them to another command. $? holds the exit status of the last command, letting you branch on success or failure. $$ is the script’s process ID, commonly used to create unique temporary files. IFS (Internal Field Separator) controls how Bash splits words; changing it lets you parse lines or comma-separated values reliably.
How Positional Parameters Work
When you run ./script.sh foo bar baz, the shell assigns $1 = foo, $2 = bar, $3 = baz. If you have more than nine arguments, you must use ${10}, ${11}, etc., with braces. The shift command moves parameters left: shift makes $2 become $1, $3 become $2, and so on. This is handy for processing options in a loop. $@ and $* both expand to all positional parameters, but they differ in quoting: "$@" treats each argument as a separate quoted string, while "$*" joins them into a single string separated by the first character of IFS (usually a space). For most purposes, "$@" is the correct choice because it preserves spaces within arguments.
Exit Status and Error Handling
Every command in Bash returns an exit status: 0 means success, any non-zero value means failure. $? captures that status immediately after the command runs. A common pattern is:
if ! some_command; then
echo "Error: some_command failed" >&2
exit 1
fi
Alternatively, you can check $? explicitly:
some_command
if [ $? -ne 0 ]; then
echo "Failed" >&2
exit 1
fi
Always check $? right after the command you care about; any intervening command (like an echo) will overwrite it. For scripts that must be robust, set set -e to exit on any error, but be aware that commands in conditionals and pipelines may not trigger it as expected. A more controlled approach is to check $? after each critical step.
Using IFS for Parsing
The Internal Field Separator (IFS) determines how Bash splits unquoted expansions. By default, it is space, tab, and newline. Changing IFS to a comma lets you read comma-separated values easily:
data="apple,banana,cherry"
IFS=',' read -ra fruits <<< "$data"
for fruit in "${fruits[@]}"; do
echo "Fruit: $fruit"
done
This prints each fruit on its own line. Another common use is reading a file line by line while preserving leading/trailing spaces:
while IFS= read -r line; do
echo "Line: $line"
done < file.txt
The -r flag prevents backslash escapes from being interpreted. Remember to restore IFS after changing it, or better, set it only for a single command as shown above.
Common Mistakes and Pitfalls
- Forgetting to quote variables:
"$1"preserves spaces;$1splits on IFS. Always quote unless you deliberately want word splitting. - Using
$?after another command: The exit status is overwritten by every command, includingecho. Capture it immediately. - Assuming
$@and$*are the same: They differ when quoted."$@"is almost always what you want. - Modifying IFS without restoring it: This can break subsequent loops and expansions. Use
IFS=',' read ...to scope the change. - Forgetting that
$0may not be the full path: It depends on how the script was invoked. Usebasename "$0"to get just the script name.
Frequently Asked Questions
What is the difference between $@ and $*?
$@ and $* both expand to all positional parameters, but when quoted, "$@" expands to each argument as a separate word, while "$*" expands to a single word with arguments joined by the first character of IFS (usually a space). Use "$@" to preserve arguments with spaces.
How do I handle more than 9 arguments?
Use ${10}, ${11}, etc., with braces. Alternatively, use "$@" to loop over all arguments, or shift to process them sequentially.
Why does my script fail when the filename has spaces?
Because you likely used $1 unquoted. Always use "$1" to keep the filename as a single word. The same applies to all variable expansions.
What does set -e do and why might I avoid it?
set -e makes the script exit immediately if any command returns a non-zero status. It can be helpful for catching errors, but it can also exit unexpectedly on commands that legitimately return non-zero (like grep when no match is found) unless you handle them in conditionals. Many scripters prefer explicit $? checks for control.
How can I make a temporary file unique to my script?
Use the process ID $$ in the filename, e.g., tmpfile="/tmp/myscript.$$". For better security, use mktemp which creates a unique file with proper permissions.
Is IFS only for reading input?
No, IFS also affects word splitting in all unquoted expansions and command substitution. For example, for word in $string splits on IFS. Changing it globally can have broad effects, so scope it carefully.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Campus Tech Innovation Hubs: What They Are
- Poco C51 Airtel Prepaid Locked Variant India?
- Jenkins vs GitHub Actions: Which CI/CD Fits Your Team?
- Turn Off Backup Encryption in iTunes?
- Shared VPS Hosting: Is It Better?
- Disk Defrag Pro: What It Does and Whether You Need It