Another approach is reformulating the problem as a pure problem of running a command with the input from a stream and massaging that stream to fit your use case. Ie, you want a command to operate on a stream of data and this data may come from stdin and/or another stream(s).
AND
If its stdin and another stream it should be pretty straightforward using cat
echo bar |
cat - <(echo biz) |
cat -A
# output: bar$biz$
This will pipe the contents of stdin and the output of the process substitution echo bar to the stdin of cat -A.
OR
Or on the other hand is a bit trickier. Let's say you want to run a command with input from stdin but fallback to something else if nothing was passed to stdin.
In this case an approach is reformulate the problem as combining streams (including a delimiter sequence say two null-bytes) and sinking the stream IFF stdin is non-empty by using sed and matching the delimiter in the combined stream.
echo bar |
cat - <(printf '\x0\x0\n') <(echo biz) |
sed \
-e '1{/\x0\x0/s@@@;N;s@\n@@}' \
-e '1!{/\x0\x0/s@@@;q}' | # stdin was non-empty, sink the rest
cat -A
# output: bar$
< /dev/null |
cat - <(printf '\x0\x0\n') <(echo biz) |
sed \
-e '1{/\x0\x0/s@@@;N;s@\n@@}' \
-e '1!{/\x0\x0/s@@@;q}' | # stdin was non-empty, sink the rest
cat -A
# output: biz$
We can combine this approach with xargs -I% for an additional fallback. It uses process substitution but other than that it should be pretty POSIX compatible.
#!/bin/bash
# This script takes a list of paths from stdin
# IFF it's empty the list of files is the existing file 'foo'
# Each file and/or directory in this list is passed to stat
# IFF this list is empty we run stat on the current directory
combined_stream() {
if [ -t 0 ]; then
cat <(printf '\x0\x0\n') <(find foo -type f 2> /dev/null)
else
cat - <(printf '\x0\x0\n') <(find foo -type f 2> /dev/null)
fi
}
combined_stream |
sed \
-e '1{/\x0\x0/s@@@;N;s@\n@@}' \
-e '1!{/\x0\x0/s@@@;q}' | # stdin was non-empty, sink the rest
xargs -I% stat % |
grep . || stat .