Skip to content
Linux Basics: Connect Generated Inputs with Bash Process Substitution

Linux Basics: Connect Generated Inputs with Bash Process Substitution

October 20, 2026

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 1

1. 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"
fi

Run it:

bash process-compare.sh

Output:

Same items after sorting

Each <(...) 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.sh

Output:

preview:8080
production:443

paste 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.sh

Output:

a:100:east
b:200:west

Unlike 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_dir

References

Acknowledgements

This post was created with assistance from AI.

Last updated on