# Quoting, Word Splitting and Globbing — Bash / Shell Scripting

Source: https://www.skillbyai.com/en/bash/v-quoting

> Quote variables correctly to prevent word splitting and unexpected glob expansion.

## The most important rule in Bash

After Bash expands an **unquoted** variable or command substitution, it performs **word splitting** (breaking the result on spaces, tabs and newlines, controlled by `IFS`) and **pathname expansion** (treating `*`, `?` and `[...]` as file patterns). That is why `rm $file` with `file="my report.txt"` tries to delete two files, `my` and `report.txt`, and why a variable containing `*` may expand into a list of files. The fix is simple: **double-quote expansions**: `rm "$file"`, `cp "$src" "$dest"`, `for f in "$@"`. **Double quotes** still allow `$var`, `$(cmd)` and `$((math))` inside them but prevent splitting and globbing. **Single quotes** prevent all expansion: `'$HOME'` is the literal text `$HOME`. To include a single quote inside a single-quoted string, close and reopen: `'it'\''s'`, or use `$'...'` ANSI-C quoting, which also understands `\n` and `\t`. Leave expansions unquoted only when you deliberately want splitting or globbing, and then say so in a comment.

## Why quotes matter

The unquoted version breaks on a file name with a space.

```bash
file="monthly report.pdf"
touch "$file"

ls -l $file      # WRONG: ls receives two arguments, "monthly" and "report.pdf"
ls -l "$file"    # right: one argument

pattern="*.log"
echo $pattern    # expands to matching files (or stays *.log if none match)
echo "$pattern"  # prints *.log literally

echo 'Single quotes keep $HOME literal'
echo "Double quotes expand $HOME"
printf '%s\n' $'Tab:\there, newline next\nline 2'
```

## Putting words in a sealed envelope

Double quotes put the value in a sealed envelope: however many spaces or asterisks are inside, it travels as one item. Without the envelope, the shell tips the contents out and sorts them into separate piles.

**Quiz:** A variable holds "my file.txt". What happens with `rm $f` (unquoted)?

- [ ] The file "my file.txt" is removed
- [x] rm receives two arguments, "my" and "file.txt"
- [ ] Bash refuses to run the command
- [ ] Nothing; quotes are optional

*Answer:* rm receives two arguments, "my" and "file.txt". Unquoted expansion undergoes word splitting on the space.
