Linux Basics: Connect Generated Inputs with Bash Process Substitution
Some commands accept two filenames but only one standard input. Bash process substitution supplies generated streams where filenames are expected, without creating named intermediate files yourself.
These examples were tested on Linux with GNU Bash 5.2.37. Use Bash rather than sh. No administrator access is needed.
Prepare a scratch directory
You need Bash, a text editor, and the diff, sort, paste, join, mktemp, rm, and rmdir utilities. Keep using the same terminal. Save each named source file in this scratch directory before running its command. Calling bash explicitly avoids changing executable permissions.
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 11. Compare lists while ignoring their original order
Save this as process-compare.sh:
#!/usr/bin/env bash
export LC_ALL=C
if diff -q <(printf '%s\n' pear apple | sort) \
<(printf '%s\n' apple pear | sort) > /dev/null; then
printf 'Same items after sorting\n'
else
status=$?
printf 'Comparison status: %d\n' "$status"
fiRun it:
bash process-compare.shOutput:
Same items after sortingEach <(...) becomes a readable filename for one sorted stream. There must be no space between < and (. The space between diff arguments is still required. diff returns zero for equal input, one for differences, and two for trouble. Sorting preserves duplicate lines, so this comparison still notices different duplicate counts.
2. Pair corresponding lines from two streams
Save this as process-pair.sh:
#!/usr/bin/env bash
paste -d ':' <(printf '%s\n' preview production) \
<(printf '%s\n' 8080 443)Run it:
bash process-pair.shOutput:
preview:8080
production:443paste combines the first lines, then the second lines. It matches positions, not keys. If one stream is shorter, its missing fields become empty, so validate lengths when that would indicate bad data. This example’s labels do not contain the chosen delimiter.
3. Join generated records by a shared key
Save this as process-join.sh:
#!/usr/bin/env bash
export LC_ALL=C
join -t ':' \
<(printf '%s\n' 'b:200' 'a:100' | sort -t ':' -k1,1) \
<(printf '%s\n' 'a:east' 'b:west' | sort -t ':' -k1,1)Run it:
bash process-join.shOutput:
a:100:east
b:200:westUnlike paste, join matches the first field here. Both inputs are sorted by that field with the same delimiter and locale. By default, records without a matching key are omitted. Keep field values free of the separator for this simple format; it is not CSV parsing.
Keep in mind
The producer commands run asynchronously. The receiving command’s status does not, by itself, prove that every producer succeeded. These demonstrations use fixed, local data. For a workflow where a failed producer could be mistaken for empty or valid input, produce and check intermediate files explicitly before comparing or joining them. Process substitution requires Bash support plus operating-system support such as /dev/fd or FIFOs; do not run these scripts with sh.
Clean up
In the same terminal, remove only the files created for these examples, return to your original directory, and remove the empty scratch directory:
rm -- process-compare.sh process-pair.sh process-join.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirReferences
- GNU Bash manual: Process Substitution
- GNU Coreutils manual: paste
- GNU Coreutils manual: join
- GNU Diffutils manual: Invoking diff
Acknowledgements
This post was created with assistance from AI.