Exit Codes, &&, and ||
Prerequisites: How the shell runs commands
Every command returns an exit status: 0 for success, 1–255 for
failure. Bash uses these to decide what to run next.
&& and ||
a && b— runbonly ifasucceeded.a || b— runbonly ifafailed.
mkdir project && echo "Created project"
mkdir project 2>/dev/null || echo "Couldn't create project (it already exists)"
cd project && touch README.md && ls
Created project
Couldn't create project (it already exists)
README.md
Chains like cd project && make && ./run-tests stop at the first failure
— you'd never want to run tests if the build failed.
; runs regardless
a ; b runs b after a, whether a succeeded or not.
true, false, and $?
true
echo "true returns $?"
false
echo "false returns $?"
grep -q "needle" <<< "haystack"
echo "grep returns $? when it finds nothing"
true returns 0
false returns 1
grep returns 1 when it finds nothing
grep -q ("quiet") prints nothing and only reports, through its exit
status, whether it found a match — perfect for conditions.
Setting your own exit status
exit N ends a script with status N. Scripts should exit 0 on success
and non-zero on failure, so that other scripts, cron, and CI systems can
tell whether they worked.
Common mistakes
a && b || clooks like if/else but isn't: ifbfails,cruns too. For real if/else logic, useif(next lesson).- Ignoring failures: a script that keeps going after a command fails can
do real damage (for example,
cdfails and the nextrmruns in the wrong folder). Level 3's strict mode helps.