Quoting Pitfalls and Why to Always Quote Variables
In this page:
Word Splitting on Unquoted Variables
When a variable containing spaces is used unquoted, bash splits it into multiple separate words on IFS before passing them to a command, which usually is not what was intended.
Example: Word Splitting on Unquoted Variables
#!/bin/bash
count_args() { echo "received $# argument(s)"; }
phrase="hello there world"
count_args $phrase
count_args "$phrase"
Login to try C/C++/Java/PHP code in the editor
Accidental Globbing
An unquoted variable whose value contains glob characters like * gets expanded against real filenames in the current directory, which can silently turn one literal string into a list of unrelated filenames.
Example: Accidental Globbing
#!/bin/bash
touch star_demo_a.txt star_demo_b.txt
pattern="star_demo_*.txt"
echo "unquoted (expands against real files): $pattern"
echo unquoted: $pattern
echo "quoted (kept literal): \"$pattern\""
rm -f star_demo_a.txt star_demo_b.txt
Login to try C/C++/Java/PHP code in the editor
Disappearing Empty Variables
An unquoted empty (or unset) variable expands to nothing at all, effectively vanishing from the command line, which can shift what the next real argument is interpreted as. Quoting keeps it as a genuine empty-string argument.
Example: Disappearing Empty Variables
#!/bin/bash
show_args() {
echo "count: $#"
for a in "$@"; do echo "[${a}]"; done
}
empty_var=""
show_args $empty_var second
echo "---"
show_args "$empty_var" second
Login to try C/C++/Java/PHP code in the editor
A Safe Default Habit
Quoting every variable expansion by default, and only deliberately leaving one unquoted when word splitting or globbing is actually wanted, avoids an entire category of subtle bugs.
Note: Tools like shellcheck flag most unquoted-variable mistakes automatically and are worth running on any real script.
Example: A Safe Default Habit
#!/bin/bash
filename="my report.txt"
touch "$filename"
if [[ -f "$filename" ]]; then
echo "file with a space in its name handled correctly"
fi
rm -f "$filename"
Login to try C/C++/Java/PHP code in the editor
- Leaving a variable unquoted and assuming it will always be treated as one value, when Bash actually word-splits it on whitespace first.
- Forgetting an unquoted variable containing
*or?gets glob-expanded against real filenames in the current directory. - Believing quoting is only needed for values that "might have spaces"; an empty unquoted variable can also vanish entirely and shift argument positions.
- Unquoted variable expansions undergo word splitting (on IFS) and filename globbing before the command runs.
"$var"prevents both word splitting and globbing, preserving the variable's exact value as one argument.- An unquoted empty variable disappears completely rather than becoming an empty argument, which can shift positional arguments unexpectedly.
- As a default habit, quote every variable expansion unless you specifically want word splitting or globbing to happen.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first:
- Quoting Pitfalls and Why to Always Quote Variables
- set -euo pipefail as a Script Header
- Structuring a Script (Functions, main() Pattern, Exit at the End)
- Idempotent Scripts (Safe to Re-Run)
- Logging in Scripts (Timestamped log Function)
- Writing Portable Scripts (Bash-isms vs POSIX sh)
- Capstone: A Real-World Backup/Cleanup Script