Warm tip: This article is reproduced from serverfault.com, please click

Clean way to duplicate stdin

发布于 2020-11-28 15:46:47

I want to pass stdin to two different processes. What are some nice clean ways to do this?

(I'm proposing a tempfile based way as an answer below, but maybe there are better ways?)

GitHub's "git lfs pre-push" pre-push hook reads stdin. I want to install a second pre-push check, e.g. the WIP check I find in pre-push.sample. This means I need to save stdin in some reasonable way, so that the commits can be read by both "git lfs pre-push" and by the "while read local_ref local_sha remote_ref remote_sha" loop.

Questioner
Hugo
Viewed
0
glenn jackman 2020-11-29 00:28:25

You could use tee with an output process substitution.

Here I'll put the individual check code into functions for clarity:

check1() {
  git lfs pre-push "$@"
}

check2() {
  while read -ra variables; do
    : ...
  done
}

# redirecting to /dev/null so you don't get the original input as well
tee >(check1) >(check2) >/dev/null

I'm not sure of the limitations, but you can do an arbitrarily large number of checks this way:

tee >(check1) \
    >(check2) \
    >(check3) ...

A demo:

check1() { while IFS= read -r n; do echo $((n*5)); done; }
check2() { while IFS= read -r line; do echo ">>>$line<<<"; done; }
seq 101 100 1101 | tee >(check1) >(check2) >/dev/null

output

505
>>>101<<<
1005
1505
2005
2505
3005
3505
>>>201<<<
4005
4505
>>>301<<<
5005
>>>401<<<
5505
>>>501<<<
>>>601<<<
>>>701<<<
>>>801<<<
>>>901<<<
>>>1001<<<
>>>1101<<<

Since both checks are running in subshells, the output order is indeterminate.