Every command reports success or failure
When any command finishes, it hands the shell an exit code: 0 means success, anything else (1-255) means some kind of failure. The special variable $? holds the exit code of the last command.
This is the shell's version of true/false, and it's what if actually checks. A useful pair to see it with: grep -q pattern file searches quietly (q = print nothing) and only reports through its exit code: 0 if found, 1 if not.
Code exercise · bash
Run it. true and false are tiny commands that just succeed and fail. Then grep -q reports found/not-found purely through $?.
if, then, else, fi
if [ -f notes.txt ]; then echo "notes.txt exists" else echo "notes.txt is missing" fi
Surprise: [ is itself a command (called test) that exits 0 or 1. That's why the spaces inside the brackets are mandatory. Its most useful checks:
| test | true when |
|---|---|
[ -f path ] | a file exists there |
[ -d path ] | a directory exists there |
[ "$a" = "$b" ] | strings are equal |
[ "$n" -ge 5 ] | number ≥ 5 (also -eq, -lt, -gt) |
Always quote variables inside [ ] ("$age", not $age), or empty values break the test.
Code exercise · bash
Run it. One if for a file we created, one for a file that doesn't exist, plus a script reading a number from stdin. Type a number in the Input box if your editor has one (this run feeds it 21 automatically).
if without if: && and ||
Because every command reports an exit code, bash can chain commands on success or failure without writing a full if block:
a && b: run b only if a succeeded (exited 0)a || b: run b only if a failed (exited non-zero)
So mkdir reports && cd reports only enters the directory if it was actually created, and grep -q error app.log || echo "clean" speaks up only when nothing was found. These two operators are everywhere in real scripts and one-liners — they are the practical payoff of exit codes even when you never type $?.
Don't confuse || with the pipe | from unit 5: the pipe moves data between commands regardless of success; || and && decide whether the next command runs at all.
Code exercise · bash
Run it. Three chains: the first succeeds and continues, the second fails and falls back to its || side, and the third combines both into a tiny found/not-found report.
Quiz
What does `command1 && command2` do?
Quiz
Why does `if [ -f notes.txt ]` need spaces after [ and before ]?
Code exercise · bash
Your turn: a password gate. Read one line from stdin into `word`. If it equals `open sesame`, print `the cave opens`, otherwise print `nothing happens`. The test input is "open sesame". Expected output: ``` the cave opens ```