Shell, explained
Why quote your variables: rm $f vs rm "$f"
rm "$f"
Without quotes, bash splits a variable's value on spaces (and expands any * in it) before the command runs. With f="old notes.txt", rm $f gets two arguments, old and notes.txt, and deletes notes.txt: a different file. rm "$f" gets the one name you meant.
rm $f: one name becomes two
Tap $f to follow it. In bash this printed rm: old: No such file or directory, and deleted notes.txt.
Tap a word to follow it
$f was not in quotes, so the space in its value splits it into two words.
rm receives 2 arguments
rm "$f": one name stays one name
The quotes keep the value together, then disappear before rm runs.
Tap a word to follow it
rm receives 1 argument
Part by part
rm- Deletes each file it is given as an argument.
$f- Replaced by the variable's value, then split on spaces and expanded if it contains * or ?.
"$f"- Replaced by the value, kept as exactly one argument.
Common mistakes
A * hiding in a variable
With f="*.txt", rm $f deletes every .txt file: the * is expanded after the variable is. rm "$f" looks for a file literally named *.txt.
$@ instead of "$@" in scripts
To pass a script's arguments on unchanged, write "$@". Unquoted, every argument with a space gets split again.
Try it
$ f="old notes.txt"; printf "[%s]\n" $fPrints two bracketed words.
$ f="old notes.txt"; printf "[%s]\n" "$f"Prints one.
$ echo "$HOME"Double quotes still expand variables; single quotes do not.
Questions
Does zsh do the same?
No: zsh does not split unquoted variables by default, so rm $f works there. But scripts usually run in bash or sh, which do split, so quote anyway.
What is the difference between single and double quotes?
Inside "double quotes", $variables and $(commands) are still expanded, but the result stays one word. Inside 'single quotes', nothing is expanded at all.
When is it safe to leave a variable unquoted?
Almost never by accident. The rare exception is when you want splitting on purpose, such as a list of flags, and in that case an array is usually the better tool.
Terminaster
Ask about any command and get a picture like this one.
The Terminaster tutor draws these visuals for your own questions, then turns what you learned into spaced-repetition cards so it sticks.
The ideas behind it
Quoting and escaping
Shell quoting is syntax the shell consumes while building command arguments. Single quotes preserve every enclosed character literally; double quotes still allow parameter, command, and arithmetic expansion while suppressing word splitting and pathname expansion; an unquoted backslash protects the next character, except that backslash-newline continues the line.
Shell parameter expansion
Parameter expansion replaces forms beginning with $ with a parameter's value or a transformation such as a default, required-value check, length, or pattern removal.