Course outline · 0% complete

0/29 lessons0%

Course overview →

Decisions: if, test, and exit codes

lesson 8-3 · ~13 min · 23/29

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 $?.

[ -f notes.txt ]runs and exits…exit 0exit 1then: echo existselse: echo missingif doesn't check true/false, it checks the exit code of a command
The condition of an if is a command. Exit code 0 takes the then branch, anything else takes the else branch.

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:

testtrue 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 ```