[ home ]

Bash process-substitution

This is a really nice feature in bash, avoiding the use of temporary files for commands that must receive input (or send output) via filename-arguments.

Problem

Some commands like paste(1) work on multiple files, the names of which are passed on the command-line:

    NAME
         paste -- merge corresponding or subsequent lines of files
        
         SYNOPSIS
              paste [-s] [-d list] file ...

paste(1) basically takes 1 line from each specified file, and concatenates these lines using separators:

    $ jot 3 10 > a
    $ jot 3 20 > b
    $ paste -d , a b
    10,20
    11,21
    12,22

Assuming files a and/or b are temporary outputs from other commands in a chain, in order to use paste(1), temporary files would be used.

Solution

Bash's process-substitution syntax creates an on-the-fly fifo, reading or writing data from/to a child-process:

    cat <( jot 3 10 )
    10
    11
    12

(The fifo-name is transparently inserted into the command-line, as if a temporary file were used.)

The first example, using this trick, can be rewritten to:

    paste -d , <( jot 3 10 ) <( jot 3 20 )
    10,20
    11,21
    12,22

Similar for >( sed 's/^/> /' > read_output_file ) or similar, to create a process reading the command's output, written to its output-file argument:

    $ cp a >( sed 's/^/> /' > out )   
    $ cat out
    > 10
    > 11
    > 12

(not-so-useful example, creating a sort of filter before writing the command's output to disk)