I apologize in advance if this is a duplicate question. I did make an effort to search/check before asking here.

I'm comfortable with writing one-liners like this:

foocommand && foocommand2 && foocommand3

The idea being that I only want subsequent commands to run if the previous one was "successful".

I'm writing a somewhat lengthy script and this one-liner isn't feasible because it looks like a huge block of confusing code to everyone else.

I want to space out the commands and write comments inbetween them in the script. How can I do this and still have the equivalent of && in there?

  • 4
    This bears repeating: && doesn't mean the subsequent command will run if the previous one was successful. It means the command will run if the collective result of all the previous commands in the command list is success. You may know this, but future readers may misunderstand. – kojiro Feb 3 '13 at 0:41
  • 1
    Also just as a note, this behavior you're describing that comes from ||and && (as opposed to | or &) is called short circuiting. The behavior used with the latter operators is called eager evaluation. – AndyPerfect Feb 3 '13 at 2:03
  • 7
    @kojiro: I don't see the distinction. a && b && c will only run b if a succeeds, so "it only runs c if b succeeds" and "it only runs c if a and b both succeed" are equivalent statements: b can't succeed unless a succeeded. – ruakh Feb 3 '13 at 6:13
  • 1
    @ruakh a || b && c is more illustrative. – kojiro Feb 3 '13 at 11:49
  • 8
    @ruakh no, true || false && echo hi will output hi. The specification reads, The operators "&&" and "||" shall have equal precedence and shall be evaluated with left associativity. – kojiro Feb 3 '13 at 22:31

You can do it like this:

ls -lh &&
    # This is a comment
    echo 'Wicked, it works!'

I hope I understood what you asked correctly.

  • Thanks. This is the closest to what I was hoping to do. And it makes it very easy to convert back into a one liner if needed. – Mike B Feb 2 '13 at 21:18
  • Mike, since you're concerned about code cleanliness, a common convention is to indent the 2-N sections of the chain underneath the first. – jblaine Feb 13 '13 at 19:42
  • @jblaine I'm not sure I understand what you mean. Can you please elaborate? – Mike B Feb 16 '13 at 19:41
  • Mike, Stackexchange won't let me format my answer properly, so here is all I meant: indent – jblaine Apr 3 '13 at 19:03
  • @jblaine Good point, edited to indent the lines. – Volker Siegel Aug 21 '14 at 4:18

You can change the shebang line to

#!/bin/bash -e

After any error, the script will stop.

  • 1
    Interesting. I'll keep that in mind. Thank you. – Mike B Feb 2 '13 at 21:19
  • saves me from typing set -e when I need it – Silverrocker Feb 2 '13 at 21:38
  • @Silverrocker It is POSIX too (except for the bash part of course). The POSIX shell takes a bunch of options that are applicable to set. Or vice versa? set is a way of setting shell command line options within the script. – Kaz Feb 3 '13 at 3:38
  • 7
    Unfortunately, there are a number of standard utilities that don't follow the usual exit-status conventions, so -e can misbehave. For example, you probably don't want your script to terminate every time you diff two non-identical files. You can, of course, work around this by appending || true (or perhaps || [ $? = 1 ]) to such commands, but the OP mentions an "everyone else" who will have to read this script, and said "everyone else" will probably not be used to having to cope with -e. – ruakh Feb 3 '13 at 6:23
  • 4
    I used to put the -e on the she-bang, until one admin of my company kept launching my scripts with bash myscript.sh, so it ignored the -e. Now all my scripts have a set -e in the second line. – Carlos Campderrós Feb 4 '13 at 8:00

If you don't like the set -e idea, maybe you can invert the logic.

foocommand || exit 1
foocommand2 || exit 2
foocommand3 || exit 3

More usefully, replace exit with something to print a useful error message, then exit. Inside a function, of course, you want return instead of exit.

  • 11
    Or foocommand || exit to exit with foocommand's exit status if non-zero. – Stéphane Chazelas Feb 2 '13 at 21:10
  • How does this work? Is it like in C - if the left argument evaluates to TRUE, the no more arguments are checked? – Vorac Mar 29 '13 at 15:39
  • Yes, that's right. It's a common idiom in Lisp (and functional languages in general, I suppose) and in Perl. – tripleee Mar 30 '13 at 8:14

You can use if else fi blocks instead.

if foocommand; then

  # some comments

  if foocommand2; then

    # more comments


It's a little more readable.

Alternatively you can just use \ to break your big 1 liner into several lines

foocommand && \
  # some comment
  foocommand2 && \
    # more comment

But of course this can be confusing to the untrained eye.

  • 4
    I don't think the \ is necessary there. – Samuel Edwin Ward Feb 3 '13 at 1:49
  • You are right. Force of habit. – lmcanavals Feb 3 '13 at 2:15

You could consider using nested if statements. Other option is to use curly's to group like { true && echo hi; } || echo huh

Update 1:

Here's an example without newlines/comments:

{ { false && echo "inner true"; } && { echo "inner true" && true; } || { echo "inner false" && false; } || echo "outter false"; }
  • @Stephane Thanks for adding semicolon. I've been using my phone to reply so I haven't been double checking my answers. :) – livingstaccato Feb 2 '13 at 21:52
  • Interesting idea. Yeah, I had thought of nested if statements but if I'm chaining a lot of stuff together it might get messy. – Mike B Feb 2 '13 at 22:38

Split each sequence of commands into functions:

big_block_1() {
  # ...
big_block_2() {
  # ...
big_block_3() {
  # ...

big_block_1 && big_block_2 && big_block_3

I always like to write a "fail" function which lets me specify the thing I was going to do when the failure occurred and then use the || pattern. Like the following:

function fail() {
  echo "Failure: ${@}"
  exit 1

foocommand || fail "couldn't foo"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.