Skip to content

Process Substitution

Process substitution is a powerful Bash feature that enables inter-process communication by redirecting the input or output of commands to temporary files or named pipes. This allows commands to interact with the output of other processes as if they were files, eliminating the need for manual temporary file creation. The syntax uses <() for input redirection and >( ) for output redirection, enabling complex pipelines and comparisons between command outputs.


Understanding Process Substitution

Process substitution leverages temporary files or FIFOs (named pipes) to pass data between commands. When using <(), the shell creates a temporary file containing the output of the command inside the parentheses, which can then be treated as a file argument. Similarly, >( ) redirects the output of a command to a named pipe, which another command can read from.

This technique is particularly useful for scenarios like comparing outputs, feeding data into commands, or integrating with tools that expect file inputs.


Input Redirection with <()

The <() syntax allows a command's output to be treated as a file input. For example:

# Pass the output of 'echo' into 'cat'
cat <(echo "Hello, World!")

This is equivalent to creating a temporary file with the output of echo and passing it to cat.

Example: Comparing command outputs

# Compare the output of two commands using 'diff'
diff <(ls -l /etc) <(ls -l /usr)

This is useful for verifying if two commands produce identical results without manual file handling.


Output Redirection with >( )

The >( ) syntax redirects a command's output to a named pipe, which can be consumed by another command. For example:

# Redirect output to 'wc -l' while preserving stdout
echo "Data" | tee >(wc -l)

Here, tee writes the input to both stdout and the named pipe, which wc -s reads to count lines.

Example: Logging and processing output

# Log output to a file and process it in real-time
some_command | tee >(grep "ERROR" > error.log)

This splits the output: one stream goes to stdout, and another is filtered and saved to error.log.


Use Cases and Best Practices

  • Compare command outputs: Use diff <(cmd1) <(cmd2) to check for differences.
  • Avoid temporary files: Use process substitution instead of manually creating files for inter-process data transfer.
  • Combine with other tools: Pair with sort, uniq, or awk for advanced data manipulation.
  • Be cautious with side effects: Ensure commands inside >( ) do not inadvertently modify the environment or rely on file paths.

Key takeaways

  • <() treats a command's output as a file input, while >( ) redirects output to a named pipe.
  • Use process substitution for comparing command outputs, logging, or integrating with file-based tools.
  • Always verify that commands inside substitutions behave as expected in isolated contexts.
  • Avoid overcomplicating pipelines; use process substitution for specific, targeted data flow tasks.
  • Modern Bash (3.0+) supports this feature, but be mindful of compatibility in legacy environments.