Command Syntax, Quoting, Expansion, and Exit Status
Most shell bugs are not caused by a mysterious Bash feature; they come from misunderstanding how Bash turns text into commands. Quoting, expansion, redirection, and exit status are therefore foundational—not optional details.
Learning objectives
By the end of this lesson
- Read a Bash command as shell syntax rather than as a single text string.
- Explain the practical effects of single quotes, double quotes, and unquoted expansions.
- Recognize parameter expansion, command substitution, arithmetic expansion, globbing, and word splitting.
- Use ;, &&, ||, and newlines intentionally based on exit status.
- Inspect and preserve exit status without accidentally overwriting it.
1. Bash does not execute a command string all at once
The shell reads syntax, recognizes operators and reserved words, performs expansions, applies redirections, and then executes a builtin, function, or external command. The order matters.
flowchart TD A["Source text"] --> B["Parse shell syntax"] B --> C["Perform expansions"] C --> D["Word splitting / pathname expansion where applicable"] D --> E["Apply redirections"] E --> F["Execute command"] F --> G["Collect exit status"]
This model explains why a variable containing spaces can become
multiple arguments when unquoted, why *.log can expand
to many filenames, and why redirection syntax can change where
errors appear.
2. Quoting controls interpretation
$value
"$value"
'literal $HOME'
space\ here
name='release candidate'
printf '<%s>\n' "$name"
# Correct: one pathname argument even if it contains spaces
target="$HOME/devops-academy/bash/data/build report.txt"
printf 'path=%s\n' "$target"
# Single quotes suppress expansion
printf '%s\n' '$HOME is not expanded here'
# Double quotes allow expansion but preserve the value as one argument
printf '%s\n' "$HOME is expanded here"
Quote parameter expansions unless you specifically require word
splitting or pathname expansion and can explain why. Unquoted
$variable is one of the most common sources of shell
bugs.
3. Learn the major expansion families
Bash offers multiple expansions. They are powerful because they can replace many small helper programs, but they must be used intentionally.
project=academy
printf '%s\n' "${project^^}" # parameter expansion (Bash)
printf '%s\n' "$(( 7 * 6 ))" # arithmetic expansion
printf '%s\n' "$(printf 'generated')" # command substitution
printf '%s\n' "$HOME" # parameter expansion
# Pathname expansion (globbing) is different:
printf '%s\n' ./*.html
# Brace expansion is syntactic generation, not variable expansion:
printf '%s\n' file-{01..03}.log
Command substitution removes trailing newlines from captured output. Pathname expansion depends on filesystem contents. Brace expansion happens from shell syntax. Treat them as separate mechanisms rather than as one vague idea called “interpolation.”
4. Command lists are driven by exit status
Unix-style commands report a numeric exit status. By convention,
0 means success and non-zero indicates some kind of
failure or false condition.
true
printf 'true status=%s\n' "$?"
false
status=$?
printf 'false status=%s\n' "$status"
# Run the second command only when the first succeeds:
mkdir -p "$HOME/devops-academy/bash/tmp/demo" && printf 'directory ready\n'
# Run fallback only when the first fails:
grep -q '^needle$' missing-file.txt 2>/dev/null || printf 'needle unavailable\n'
# Semicolon/newline does not mean "only on success":
false; printf 'this still runs\n'
$? is overwritten by the next command. If you need an
exit status later, save it immediately: status=$?.
5. Redirection syntax has ordering semantics
File descriptors are introduced deeply in Chapter 3, but you should already recognize that redirections are shell syntax and that order can matter.
# stdout to file, stderr remains visible
some_command >output.log
# stdout and stderr both to the same destination
some_command >combined.log 2>&1
# These are not always equivalent:
some_command 2>&1 >output.log
some_command >output.log 2>&1
# discard expected diagnostic noise carefully
grep -q needle missing.txt 2>/dev/null
In the first combined form, Bash redirects stdout to the file and then points stderr at the current stdout destination. In the reversed form, stderr is duplicated first and may remain attached to the terminal while stdout moves to the file.
6. Hands-on lab: prove quoting and status behavior
mkdir -p "$HOME/devops-academy/bash/chapter01/lesson04"
cd "$HOME/devops-academy/bash/chapter01/lesson04"
touch 'alpha one.log' 'beta two.log'
pattern='*.log'
printf '%s\n' '--- quoted variable ---'
printf '<%s>\n' "$pattern"
printf '%s\n' '--- unquoted variable ---'
printf '<%s>\n' $pattern
printf '%s\n' '--- literal glob ---'
printf '<%s>\n' ./*.log
grep -q '^alpha$' /dev/null
status=$?
printf 'grep_status=%s\n' "$status"
if (( status == 0 )); then
printf 'match found\n'
else
printf 'no match\n'
fi
Verification checklist
7. Knowledge check
Question 1. Why is
"$variable" usually safer than
$variable?
Question 2. What does exit status 0 conventionally mean?
Question 3. Why should
status=$? immediately follow the command you care
about?
$?, so delaying the
assignment captures the wrong command's status.
8. Summary
Bash transforms source text through parsing, expansion, redirection, and command execution. Quoting determines which transformations are allowed. Exit status is the control signal behind conditions and command lists. These rules are the foundation of every later topic: variables, pipelines, functions, loops, traps, and production error handling.
9. Further reading
- GNU Bash Reference Manual — Shell Syntax, Shell Expansions, Redirections, and Lists of Commands.
- GNU Bash manual — Quoting.
- ShellCheck wiki — quoting and word-splitting diagnostics.
- POSIX Shell Command Language — portable expansion and redirection baseline.
- BashFAQ guidance on quoting and safe argument handling.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.