All the answers given so far replace cmd3
with cat
. You can also avoid running any command with:
if [ -n "$DEFINE" ]; then
alias maybe_cmd3='cmd3 |'
else
alias maybe_cmd3=''
fi
cmd1 |
cmd2 |
maybe_cmd3
cmd4 |
... |
cmdN > result.txt
That's POSIX, but note that if in a bash
script where bash
is not in sh
-mode (like with a script starting with #! /path/to/bash -
), you'll need to enable alias expansion with shopt -s expand_aliases
(or set -o posix
).
Another approach that still doesn't run any unnecessary command is to use eval:
if [ -n "$DEFINE" ]; then
maybe_cmd3='cmd3 |'
else
maybe_cmd3=''
fi
eval "
cmd1 |
cmd2 |
$maybe_cmd3
cmd4 |
... |
cmdN > result.txt"
Or:
eval "
cmd1 |
cmd2 |
${DEFINE:+cmd3 |}
cmd4 |
... |
cmdN > result.txt"
On Linux (at least), instead of cat
, you could use pv -q
which uses splice()
instead of read()
+ write()
to pass the data across between the two pipes which avoids having the data moved twice between kernel and user space.
Another option could be to define a function that runs a give command piped to or from cmd3
or not depending on $DEFINE
.
if [ -n "$DEFINE" ]; then
maybe_preprocess_with_cmd3() { cmd3 | "$@"; }
maybe_postprocess_with_cmd3() { "$@" | cmd3; }
else
maybe_preprocess_with_cmd3() { "$@"; }
maybe_postprocess_with_cmd3() { "$@"; }
fi
And then:
cmd1 |
cmd2 |
maybe_preprocess_with_cmd3 cmd4 |
... |
cmdN > result.txt
Or:
cmd1 |
maybe_postprocess_with_cmd3 cmd2 |
cmd4 |
... |
cmdN > result.txt