Pipe B to D? - A && B || C | D

Yes, in bash you can use parentheses:

(A && B || C) | D

This way the output of A && B || C will be piped into D.


You can write this as

if A; then B; else C; fi | D

You say you want to run either B or C, but A && B || C doesn't achieve that. If A succeeds, but B runs and fails, it would execute C.

Note 1: if you can somehow guarantee that B always succeeds and want to stick with a short version, then I'd still opt for

{ A && B || C; } | D

over ( ... ), as the latter unnecessarily forces a new subshell to be created, which may or may not get optimised away.

Note 2: both forms assume A produces no output, which is true in your example but not necessarily so in general. That can be avoided by

A; if [ "$?" -eq 0 ]; then B; else C; fi | D

The accepter answer is correct but it doesn't cover the potential use case to not have the output of A as the input of D. To achieve that you’ll need a stream redirection on A depending on your needs.

  • If you want to discard the output of A anyway:

    { A >/dev/null && B || C; } | D
    
  • If you want to see the output of A on the terminal:

    { A >/dev/tty && B || C; } | D
    
  • If you need the output of A as the input of a subsequent command E you’ll need an additional command group and stream redirection:

    { { A >&3 && B || C; } | D; } 3>&1 | E
    

If all this looks too arcane to you (as it does to me) I recommend that you use the special shell variable for the exit status of A and work with that:

A
if [ $? -eq 0 ]; then
  B
else
  C
fi |
D

If you want to be more concise but not too arcane I suggest this:

A; { [ $? -eq 0 ] && B || C; } | D

(See also the last part of hvd’s answer which I didn't notice when I wrote my original answer.)

Tags:

Bash

Pipe