Bash process substitution: comparison and fan‑out without temporary files
Process substitution lets bash commands consume or produce data through filename‑like paths, eliminating temp files for diff, comm, and tee patterns.
15 Mar 2026, 12:23 UTC

Bash process substitution: comparison and fan‑out without temporary files
You want to compare two sorted directory listings, or grep a pattern from a command’s output, without writing intermediate files to disk. Bash process substitution solves this by turning command output into a filename, so utilities can consume pipeline output directly. Traditional pipelines chain commands, but utilities like diff, comm, and grep -f expect file arguments, not pipe input.
How process substitution works
When bash sees <(command) or >(command), it spawns a subshell, creates a FIFO or /dev/fd/N entry pointing to the subshell’s stdout or stdin, and passes that path as the argument. The enclosing command sees a filename, reads or writes it, and data moves through the kernel pipe without touching disk.
Reading output as a file: the <()
Commands that accept a file operand can consume command output directly.
diff <(sort file1) <(sort file2)Here, sort output becomes a temporary filename that diff reads as if it were a regular file. The differing lines are reported, and bash cleans up the FIFO after the command finishes.
Expected check: run the command in bash; the line present in only one file appears in the output. If you run the same command under /bin/sh, you’ll get a syntax error because process substitution is bash‑specific.
Writing fan‑out with the >() form
When you need to fan out a stream to multiple commands, >(...) gives you a writable path. Writes to that path are fed to the subshell’s stdin.
grep pattern >(wc -l) >(grep -c another)Each >(...) creates a separate pipe. The grep pattern output fans out, and both subshells process it independently. No tee file is needed.
Portability and verification
- Confirm bash is running:
bash --version(major version 4+). - Verify process substitution works:
diff <(printf 'a b') <(printf 'a c')in bash should report the differing line. - Inspect the file descriptor: while the command runs,
ls /dev/fdwill show an entry pointing to the subshell. - Confirm non‑POSIX behavior: run the same
diffunder/bin/sh; it will fail, demonstrating the limitation.
When to avoid it
If your script must run under sh, dash, or minimal shells that don’t expose /dev/fd, fall back to explicit temp files (mktemp) or a tee‑based pipeline. Process substitution also introduces subtle ordering risks if you read from multiple <() paths sequentially without ensuring they’ve both completed.
Actionable closing
Before relying on process substitution, open a bash shell, run the verification commands above, and confirm /dev/fd entries appear as expected. If your deployment environment uses a different shell by default, substitute a mktemp + cat pattern instead. When bash is guaranteed, the pattern reduces clutter, avoids cleanup, and makes pipelines easier to read.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.