Synchronizing multiple subshells in Bash

Nov. 15, 2018, 9:23 p.m.

Let's suppose you want to diff outputs of two scripts which operate on the same resource (file). Compare contents of the file before and after a transformation in a single pass, for example.

With process substitution, like diff <(cat myfile) <(reformat myfile; cat myfile) both substitutions are started in separate subshells at the same time, so you would need a semaphore, to ensure the second process substitution is started after after the first one - otherwise you might hit a race condition.

One option is to use a named pipe for that, but it involves the creation (and cleanup) of the pipe device file.

Another option is to use a co-process (Bash 4+) for that. cat command running as the co-process would basically act as an anonymous pipe!

echo BEFORE >data.txt

( 
    coproc cat

    diff -du \
        <(sleep 5; cat data.txt; echo >&"${COPROC[1]}") \
        <(read <&"${COPROC[0]}"; echo AFTER >data.txt; cat data.txt)
)

(sleep is for demonstration purposes only)

will output

--- /dev/fd/62  2018-11-15 21:41:17.771271807 +0000
+++ /dev/fd/61  2018-11-15 21:41:17.771271807 +0000
@@ -1 +1 @@
-BEFORE
+AFTER