Skip to content
Lesson 12 of 16

Step 1 of 5 · Reading · ~3 min

Read

Execution & Pipelines

Logical Operators and Lists: &&, || and ;

After this lesson your shell runs command lists the way scripts use them: make && make install stops at the first failure, cmd || echo failed reacts to one, and ; runs the next command whatever happened. You will decide for every command in a list whether it runs, track the status the shell calls $?, and reject lists that are incomplete.

Exit status is the only signal

Every command ends with a number from 0 to 255. By convention 0 means success and anything else means failure. 127 means the command was not found and 128+n means killed by signal n. The shell keeps the last one as $?. All the operators below read it and nothing else.

The three connectors

OperatorRun the next command when
a && bthe status so far is 0
a || bthe status so far is not 0
a ; balways

A command that is skipped does not run and does not change the status. That is what makes chains behave in ways people get wrong.

Left to right, equal precedence

&& and || have the same precedence and associate to the left. Read false && echo a || echo b as (false && echo a) || echo b. The false fails, the echo a is skipped, the status is still 1, so the || runs echo b. Now true || echo a && echo b: true succeeds, echo a is skipped, and the status is still 0, so the && runs echo b. Many programmers expect b not to print, because "the or already succeeded". The shell does not remember that; it only has the current status.

The semicolon is weaker than both: it ends a list item. So false && echo a ; echo b prints b. Because every item starts from the status left by the previous one, a simple left-to-right walk with one running status implements all three rules.

Syntax errors

The grammar needs a command on each side of && and ||, so && true, true && && false and a trailing true && are invalid. A trailing ; is fine and a leading ; is not. The whole list is checked before anything runs, so nothing is printed from a list that is rejected. A real shell would wait for more input after a trailing &&; this one reports the error. Operators that belong to other lessons (|, &, redirections) are reported as unsupported.

The toy commands

No programs run here. Five behave as follows: true (status 0), false (status 1), status N (exits with N modulo 256, or 2 if N is not a number), echo words (prints them; a word that is exactly $? prints the last status) and anything else prints name: command not found with status 127. Each command that actually runs prints a trace line + followed by its words, which is how you can see what was skipped. A list ends with the line status N.

Common mistakes

  • Treating a || b && c as if c depends only on a. It depends on whichever command ran last.
  • Resetting the status to 0 when a command is skipped.
  • Giving && higher precedence than ||, as in many languages' and/or. Shells do not.
  • Splitting on the characters && in the raw text, so a quoted "a && b" breaks.

Your exercise

The starter tokenizes each line, runs single commands, and prints the trace. You write the part that parses a list and decides what runs. The most likely mistake is forgetting that a skipped command leaves the status unchanged.

Up nextSignals and the TerminalProduction Concerns

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…