Advanced

Exit status and failure

Every command reports a number, and zero means it worked. That number is how the shell knows anything, and it is also why a script that ignores it keeps running after something failed. Checking the status is the difference between a wrong result and a loud one.

What you will see

A non-zero number, commonly 2. That number is what a script branches on.

About 1 min of reading

Try It

Branch on a status.

1

Success path

ls one.txt && echo found

Before you run it, say out loud what it will print. Then open the answer.

What it prints
The listing then found - the second ran because the first worked.
2

Failure path

ls nope.txt || echo missing

Before you run it, say out loud what it will print. Then open the answer.

What it prints
An error then missing - the fallback ran because the first failed.
3

Read the number

ls nope.txt; echo $?

Before you run it, say out loud what it will print. Then open the answer.

What it prints
A non-zero number, commonly 2. That number is what a script branches on.

Data Flow

A number decides the next step.
1 Run the command
↓
2 Capture the status
↓
3 Branch on zero or not
↓
4 Report which step failed
Why this works
Fail early in a script

Stopping at the first failure is the default you want in a script. Setting that behaviour at the top, or checking after each risky step, is what prevents a script from finishing successfully having done nothing.

Non-zero is not always bad

grep returns non-zero when nothing matches, which is a normal answer rather than an error. Treating every non-zero as failure turns a legitimate empty result into a crash.

Examples

Read it right after

The status of the last command is available immediately, and $? gives it. It is overwritten by the next command, which is why checking happens on the same line or the next one.

and and or branch on it

cmd && next runs next only if cmd succeeded; cmd || fallback runs on failure. That is a readable branch for one step, and it is the shape most shell scripts should use.

A pipeline reports the last stage

In a pipeline, the status you see is the last command's. A failure in the middle is invisible unless you ask for it, which is why long pipelines need checking stage by stage.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Loops and conditionals
Previous Lesson
Loops and conditionals
Next Lesson
Environment variables
Environment variables →