Here it shows to use the || and && in a single line to concatenate the execution of commands: How can I check for apt-get errors in a bash script?

I am trying to stop a script execution if a certain condition fails,


false || echo "Obvious error because its false on left" && exit

Here it prints Obvious error because its false on the left and exits the console which is what I wanted.

true || echo "This shouldn't print" && exit

Here, there's no echo print but the exit command runs as well, i.e., the console is closed, shouldn't the exit command not run because the echo command on the right was not executed? Or is by default a statement considered false on the left hand side of an && operator?

Edit: I should have mentioned it before, my aim was to echo the error and exit if it was not clear. w.r.t to my specific case of catching errors when grouping conditions using && and ||, @bodhi.zazen answer solves the problem.

@takatakatek answer makes it more clear about the flow control and the bash guide links are excellent

@muru answer has good explanation of why not to use set -e if you want custom error messages to be thrown with alternatives of using perl and trap which I think is a more robust way and see myself using it from my second bash script onwards!

  • As far as I can tell it exits as the script is done.
    – Panther
    Jun 13, 2017 at 0:35

4 Answers 4


The problem is that || and && only skip one subsequent stanza of a command chain when the condition fails. If you write out a full block structure it makes perfect sense. What you wrote becomes this:

if ! true ; then
   echo "This shouldn't print"

What you want is this:

if ! true ; then
   echo "This shouldn't print"

When you are using Bash's shortcut conditional operators it is better to avoid mixing them. The logic is much easier to understand while you're writing it, and your readers will appreciate your good style.

  • 2
    Yes in my opinion this is much more how conditioning in bash should be written
    – derHugo
    Jun 13, 2017 at 5:32
  • @takatakatek This makes it more clear why it fails in my case. I agree that the logic is clear in this one but isn't the reason for grouping conditions using && and || is to avoid expressing them using conditional statements ?
    – kosol
    Jun 15, 2017 at 20:24
  • @kosol Yes, && and || combine two things: Testing the exit status of the previous command, and specifying a single command (or command group) to be executed (for &&) or skipped (for ||). They can be useful for very simple cases, but they can not replace fully expressed if ... then ... elif ... else ... fi blocks. I suspect you may not be aware that Bash doesn't have true boolean types seen in more sophisticated languages. If the exit status of a command is 0 (zero), Bash treats that as true/success. If the exit status is non-zero, Bash treats that as false/failure. Jun 15, 2017 at 22:34

You probably want (as pointed out by steeldriver)

true || { echo "This shouldn't print" && exit; }

Otherwise your script is reading one conditional at at time

a or b and then exit

I think you want a or (b and exit) ?

  • 4
    Actually, you must use { ... ; } (as @steeldriver suggested), or else the exit only exits the subshell, and the parent shell continues executing the script. Jun 13, 2017 at 15:00
  • I needed a ; at the end ({ ... ; };) to include that statement in a Bash script.
    – mfg
    Jan 12, 2021 at 12:05

You could start the script with:

#!/bin/bash -e

The -e ensures that the script exits the moment something returns false (or any non-zero number). A specific failure can then be avoided with something || true

Alternatively, if you want to postpone error checking until later in the script, you can use set -e:

false  # script continues happily
set -e
false  # script stops

The simplest way to fail on error is to use bash's -e option (set -e or /bin/bash -e in the shebang). However, this doesn't make it easy to send custom error messages. There are a couple of idioms that might make it simpler:

die à la Perl

Perl has a very convenient die command which prints a message to stderr and raises an exception, which usually leads to the script terminating. You can emulate this:

die () {
  print "%s\n" "$@" >&2
  exit "$ret"

false || die "Obvious error because its false on left"
true || die "This shouldn't print"

trap ERR

The trap <command> command can be used to run a command when a signal is received, or when exiting the script (trap ... EXIT), or when a command returns an error (trap ... ERR). So something like:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR


ERR_MSG="Obvious error because its false here"
ERR_MSG="This shouldn't print"

In either case, I'd suggest using at least exit 1, to indicate that the script failed. A plain exit will use the exit status of the previous command, which in these cases would be the echo or printf commands, which would usually succeed. Saving the exit status of the failing command like I have done here would be a nice-to-have.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .