Bash – Semi-asynchronous pipe

bashfifopipeshell

Assume I have the following pipe:

a | b | c | d

How can I wait for the completion of c (or b) in sh or bash? This means that script d can start any time (and does not need to be waited for) but requires complete output from c to work correctly.

The use case is a difftool for git that compares images. It is called by git and needs to process its input (the a | b | c part) and display the results of the comparison (the d part). The caller will delete input that is required for a and b. This means that before returning from the script, process c (or b) must terminate. On the other hand, I cannot wait for d because this means I'm waiting for user input.

I know I can write the results of c to a temporary file, or perhaps use a FIFO in bash. (Not sure if the FIFO will help, though.) Is it possible to achieve this without temporary files in sh?

EDIT

Perhaps it would be sufficient if I could find out the process ID of the c (or b) process in a reliable fashion. Then the whole pipe could be started asynchronously, and I could wait for a process ID. Something along the lines of

wait $(a | b | { c & [print PID of c] ; } | d)

EDIT^2

I have found a solution, comments (or still better solutions) are welcome.

Best Answer

a | b | { c; [notify];} | d

The notification can be done e.g. by a signal to a PID which has been passed in an environment variable (kill -USR1 $EXTPID) or by creating a file (touch /path/to/file).

Another idea:

You execute the next process (the one to be able to start you are waiting for) from the pipeline:

a | b | { c; exec >&-; nextprocess;} | d

or

a | b | { c; exec >&-; nextprocess &} | d