patternbashTip
Process substitution <() feeds command output as a file-like argument
Viewed 0 times
process substitutionnamed pipedifffile descriptorcommand outputconcurrent
Problem
Many commands expect filename arguments, not stdin. To compare two command outputs with diff, a naive approach requires writing to temp files first.
Solution
Use process substitution <(command) which creates a named pipe (or /dev/fd/N) that the outer command reads as a file.
diff <(sort file1) <(sort file2)
comm <(sort list1) <(sort list2)
join <(sort -k1 a.tsv) <(sort -k1 b.tsv)
diff <(sort file1) <(sort file2)
comm <(sort list1) <(sort list2)
join <(sort -k1 a.tsv) <(sort -k1 b.tsv)
Why
<(...) creates a /dev/fd/N file descriptor or a named FIFO that the shell wires up. The outer command gets a filename it can open and read, while the inner command runs concurrently.
Gotchas
- Process substitution is bash/zsh only — not POSIX sh
- The substituted process runs in a subshell; variable assignments inside do not propagate to parent
- Exit code of the substituted process is not captured by $? — you need PIPESTATUS or explicit checking
- Cannot seek in process substitution — only sequential reads work
- >() for writing is less common but works: tee >(process1) >(process2) /dev/null
Code Snippets
Process substitution examples
# Compare sorted versions of two files
diff <(sort unsorted1.txt) <(sort unsorted2.txt)
# Feed two command outputs to comm
comm -12 <(cut -f1 file1.tsv | sort) <(cut -f1 file2.tsv | sort)
# tee to multiple processes simultaneously
tee >(gzip > output.gz) >(wc -l > count.txt) > /dev/null < input.txtContext
When a command needs a filename but you want to feed it command output without temp files
Revisions (0)
No revisions yet.