Logical Operators (&&, ||, !)

The shell can chain commands by success: the double ampersand runs the next command only if the previous one succeeded, and the double pipe runs the next only if the previous one failed, letting you build and-then and or-else logic in a single line.

9 min read · 7 cards · 2 checks

Read in: English · हिन्दी · ગુજરાતી


Theory

And-then, or-else

Often you want one command to run only if another worked. Make a directory and then move into it, but only if the making succeeded. Try to open a file, or else print a warning if it failed.

The shell expresses this with two logical operators: && (and) and || (or). They chain commands together based on whether each one succeeded or failed. To understand them, you first need one idea: the exit status.

Theory

Exit status: success is zero

Every command, when it finishes, returns a hidden number called its exit status. The convention is: 0 means success, and any non-zero value means failure. (You can see the last one with echo $?.)

This is the opposite of what you might guess, zero is the 'good' result, but it makes sense: there is one way to succeed, but many different ways to fail, so non-zero values can signal different errors. The logical operators use this status to decide whether to run the next command.

Practical

&& and || in action (verified)

# && runs the next command ONLY if the first succeeded (exit 0)
$ mkdir demo && cd demo        # cd only happens if mkdir worked
$ true && echo "ran"
ran
$ false && echo "skipped"      # first failed, so this is skipped
$ 

# || runs the next command ONLY if the first FAILED (non-zero)
$ false || echo "fallback"     # first failed, so this runs
fallback
$ true || echo "skipped"       # first succeeded, so this is skipped
$

Formula

&& is 'and then', || is 'or else'

Read them out loud and they explain themselves. `A && B` means 'run A, and then run B only if A succeeded'. `A || B` means 'run A, or else run B only if A failed'.

So mkdir demo && cd demo safely enters the directory only if it was created, and ping -c1 host || echo "host down" prints a warning only when the ping fails. Chaining with && and || lets you write safe, self-checking one-liners without a full if statement.

Quiz

What does this print? false && echo "A" ; true || echo "B"

  1. Both A and B
  2. Neither A nor B
  3. Only A
  4. Only B
Show the answer

Neither A nor B

Take each part. In 'false && echo A', the first command false FAILS, and && runs the second only on SUCCESS, so echo A is skipped (no A). Then in 'true || echo B', the first command true SUCCEEDS, and || runs the second only on FAILURE, so echo B is skipped (no B). Therefore neither A nor B prints. Option A is wrong: && needs success (which false is not) and || needs failure (which true is not), so both echos are skipped. Options C and D each miss one of the two skips. The rule: && fires on success, || fires on failure, here the first command's status blocks each echo.

Think first

Why is 'success' represented by zero, of all numbers?

In most of programming, zero means false or nothing. Why does an exit status of 0 mean success? Then tap.

Show the answer

Because an exit status describes HOW a command ended, and there is exactly one way to fully succeed but many distinct ways to fail, so zero is reserved for 'no error' and the other numbers are free to name specific errors. Think of the exit status as an error code: 0 means 'zero problems, everything went fine', while 1, 2, and other non-zero values can each mean a different kind of failure (file not found, permission denied, bad arguments, and so on). If success were some non-zero number instead, you would waste a value that is far more useful for distinguishing errors. This is why it feels backwards compared to boolean true/false, in the world of exit statuses, the question is not 'true or false?' but 'how many things went wrong?', and the best answer is zero. The logical operators build directly on this: && continues when the count of problems is zero (success), and || steps in when it is non-zero (failure). Once you internalise 'zero means it worked', $?, &&, and || all click into place. Zero problems is the goal.

Summary

Key takeaways

  • Every command returns an exit status: 0 means success, any non-zero value means failure (seen via echo $?).
  • && (logical AND) runs the next command only if the previous one succeeded.
  • || (logical OR) runs the next command only if the previous one failed.
  • Read them as 'and then' (&&) and 'or else' (||).
  • Idioms: mkdir dir && cd dir (enter only if made); command || echo 'failed' (fallback on failure).
  • Success is zero because there is one way to succeed but many ways to fail, so non-zero values can name errors.
  • Memory hook: && on success, || on failure, and 0 means it worked.

Study this properly

This page is the lesson to read. In Gri-Learn the same topic is a graded deck: the self-checks are scored and your weak topics are tracked. Free to start.

Start this topic

Already have an account? Sign in

More from Shell Scripting in Linux

Gri-Learn · syllabus-mapped B.C.A. lessons in English, Hindi and Gujarati

Logical Operators (&&, ||, !) · Linux Operating System (LOS) (Minor-04) · Gri-Learn