LearnLinux FoundationsChaining

Chaining Commands with ||

|| - a hands-on Linux lab on a real virtual machine.

The or-operator runs its right side only when the left side fails. Fire fallbacks with false echo recovered, rescue a failing ls, prove success keeps the gate silent, and drive the cmd && A B guard line down both branches, all in the practice terminal.

In the and-operator lesson, one failure was final. You ran false && echo skipped and watched the line print nothing at all: false failed, the && gate closed, and everything after it was dropped.

Real work cannot always stop there. A download fails, so you reach for the backup copy. A check comes up wrong, so you print a warning. Plan A collapses, so plan B takes over. Every one of those needs the same missing piece: a way to run a command exactly WHEN something fails, not despite it.

So here is the question this lesson answers: what if a failure could START a command instead of killing the line? The shell has one two-character symbol for that, and by the end of this lesson it is yours.

The black boxes below are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. On the real machine at the end of the module, the chaining mission lets you run these for real.

The symbol is ||, two pipe characters side by side, and it is called the or-operator. It joins two commands with one rule: run the second command only if the first one failed. Read it out loud as "or else".

Quick reminder from the and-operator lesson: every command finishes with a tiny report called an exit code, 0 for success and any other number for failure. The practice commands true and false do nothing but file that report: true always succeeds, false always fails. The exit-codes lesson later in this module digs into the numbers themselves; today you only need success versus failure.

Both chaining operators read that same report and open on opposite results.

The shell borrowed && and || from the C language at Bell Labs in the mid 1970s, and the trick has a name: short-circuit evaluation. The right side is not even started unless the left side's report demands it.

Time to answer the opening question. Build a line where the first command is false, a guaranteed failure, and the second is a message.

false || echo recovered

Before you run it, decide: last lesson taught you that a failure kills the rest of the line. Does that rule still hold here, or does recovered print?

prompt: student@linuxcamp:~$ answer: false || echo recovered output: recovered hint: The failing command, then two pipe characters, then the message: false || echo recovered

recovered printed. The failure did not kill the line, it OPENED the gate. false reported failure, || read that report, and only then ran echo recovered. This is the exact mirror of &&: same two commands, same shape, opposite trigger. And the mirror cuts both ways: if the first command SUCCEEDS, || skips its right side and the fallback never runs. You will prove that silence yourself in the challenges.

Now give || the job it was born for. Remember from the ls lesson: asking ls to list a file that does not exist is an error. There is no file called missing.txt here, so ls missing.txt will fail, and a fallback can catch it.

ls missing.txt || echo fallback

Before you run it, decide: how many lines will print, one or two?

prompt: student@linuxcamp:~$ answer: ls missing.txt || echo fallback output: ls: cannot access 'missing.txt': No such file or directory fallback hint: The ls of the missing file first, then the or-operator, then the fallback echo: ls missing.txt || echo fallback

Two lines. The first is ls complaining, and that complaint travels on a separate error channel that gets its own module later. The second line is the one || added: your fallback. Look at what actually triggered it. The or-operator never read the error text, it read the failure REPORT that ls filed on the way out. Try the real thing, or else do the safe thing: that is the everyday shape of ||.

Pause and look at what you can read now. Three symbols, three rules: the semicolon ; runs the next command no matter what, && runs it only after a success, and || runs it only after a failure. Any two-command chain you meet from now on, you can call before you press Enter.

Engineers lean on || for one job above all others: making failures loud instead of silent. Shapes like command || echo "warning: step failed" sit in nearly every real script, standing guard on steps that usually work but must never fail quietly.

At the end of the and-operator lesson, the guard line got a one-sentence preview. Now you own its second half. The pattern is command && A || B: on success run A, or else run B. One line that picks its own path.

See it as a fork before you type it. The command files its report; success lights the && branch, failure lights the || branch. This diagram starts on the failure case so you can see || catch the fall. Flip the switch to send the command down the success path instead.

{ "caption": "true && echo worked || echo failed: the exit code alone chooses which branch prints.", "command": "cmd", "start": "failure", "success": { "op": "&&", "label": "echo worked", "result": "worked" }, "failure": { "op": "||", "label": "echo failed", "result": "failed" } }

Now run the success path, using true as the command that works.

true && echo worked || echo failed

Before you run it, decide which single word will print: worked or failed?

prompt: student@linuxcamp:~$ answer: true && echo worked || echo failed output: worked hint: The command, then && with the success message, then || with the failure message: true && echo worked || echo failed

worked, and only worked. Walk the route: true succeeded, so && ran echo worked. That echo succeeded too, so when || read the report, it saw success and kept its branch shut. The failure route through this same line is yours to drive in the challenges.

One honest footnote: if A itself fails, B runs too, because || reads the report of whatever ran last. With a simple echo as A that almost never matters, and the exit-codes lesson later in this module digs deeper.

Scaffolding off. No command is shown from here on.

Earlier you saw the claim that a success keeps the or-gate shut. Prove it. Build one line: the command that always succeeds, then the or-operator, then an echo of the word skipped. If the claim is true, nothing at all should print.

prompt: student@linuxcamp:~$ answer: true || echo skipped output: hint: The always-succeeding command from the lesson, the or-operator, then echo skipped. Success means the echo never fires.

Silence, and the silence IS the proof. true reported success, so || never started its right side and skipped never printed. Line this up with the drill you opened with: false || echo recovered printed, true || echo skipped did not. The or-operator answers to failure and nothing else.

A teammate's script expects a file called target.txt. It does not exist here. Write one line that tries to list target.txt and prints the message not found when the listing fails.

prompt: student@linuxcamp:~$ answer: ls target.txt || echo "not found"|||ls target.txt || echo 'not found'|||ls target.txt || echo not found output: ls: cannot access 'target.txt': No such file or directory not found hint: List target.txt with ls, then the or-operator, then echo the message. Same shape as the missing.txt rescue.

Same two-line signature as your first rescue: the complaint from ls, then your message. This exact line is how scripts report absence without crashing: the failure is caught, named, and the script moves on. You built it from memory.

One more, from memory. Take the guard line you ran earlier and drive it down the OTHER branch: use the command that always fails as the first command, so the line prints failed and never mentions worked.

prompt: student@linuxcamp:~$ answer: false && echo worked || echo failed output: failed hint: Same guard shape as before, but the first command must be the one that always fails.

failed, and only failed. false filed its failure, && kept echo worked locked out, and the failure was still the last report standing when || read it, so echo failed ran. You have now driven the guard line down both branches yourself. One line, two outcomes, and you can call which one before you press Enter.

You earned this cheat sheet. Every line on it is one you ran yourself.

The single idea underneath: && and || read the same success-or-failure report and open on opposite results. Once you know which way the report went, every chain reads itself.

When a fallback fires and you did not expect it, the left half really did fail. Run the left command on its own and look at what it prints. The exit-codes lesson later in this module shows you how to read the failure's exact number.

You made failure useful. You fired a fallback with false || echo recovered and rescued a real failing ls. You proved that success keeps the or-gate silent, and you drove the guard line cmd && A || B down both branches from memory.

Next lesson: grouping with ( ), so several commands can act as one unit and share a single fallback. And the Chaining module ends with one real Linux machine: the chaining mission lab, where a VM boots just for you and hands you objectives built from these operators, showing no commands. You read the objective, recall the operator, and type it. That recall is what makes it stick.

Finish the remaining Chaining lessons, then go run the chains for real.

Practice Chaining Commands with || in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.