1

The accepted answer to Intersection of two lists in Bash

comm -12  <(ls 1) <(ls 2)

Uses < twice on one command.

Another answer to the same question

sort <(ls one) <(ls two) | uniq -d

Also uses < twice on one command.

What's going on here?

spraff
  • 32,570
  • 22
  • 121
  • 229
  • 4
    Are you confusing `<(...)` (process substitution) with `<...` (input redirection)? With process substitution, bash replaces the `<(...)` construct with a temporary filename, which is connected to the output of the command between the parentheses. There is no problem having multiple such filenames. – Thomas Jul 27 '21 at 10:06
  • 3
    Replace `comm -12` with `echo` and you see what's going on: `echo <(ls) <(ls)` prints something like `/dev/fd/63 /dev/fd/62` (those are the two temporary files Thomas mentioned). – Socowi Jul 27 '21 at 10:15
  • Does this answer your question? [What is the difference between using process substitution vs. a pipe?](https://stackoverflow.com/questions/51293767/what-is-the-difference-between-using-process-substitution-vs-a-pipe) – Joe Jul 27 '21 at 10:26

1 Answers1

2

The shell replaces the <(...) process substitution (hence, "substitution") with the name of a temporary file (could be a symlink to a named pipe; this is somewhat platform-dependent) which gets passed as the actual argument. You can easily see this with a utility which prints its input file names.

bash$ wc -l <(echo foo) <(printf '%s\n' foo bar)
       1 /dev/fd/63
       2 /dev/fd/62
       3 total

bash$ tail <(echo foo) <(printf '%s\n' foo bar)
==> /dev/fd/63 <==
foo

==> /dev/fd/62 <==
foo
bar

bash$ grep '^' <(echo foo) <(printf '%s\n' foo bar)
/dev/fd/63:foo
/dev/fd/62:foo
/dev/fd/62:bar
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • 2
    Not a "temporary file", but a symlink to a named pipe; `ls -Lld <(echo)`. – Joe Jul 27 '21 at 11:21
  • 1
    *Maybe* a named pipe. I think `bash` will use character devices under `/dev/fd` first when available. – chepner Jul 27 '21 at 11:25
  • 2
    @Joe, depending on the operating system capabilities detected at compile time, it may _just_ be a named pipe. Use of `/dev/fd` or `/proc/self/fd` only happens if the operating system is detected to provide them (in which case bash creates anonymous FIFO pairs and relies on the aforementioned OS facility to automatically create names for them) – Charles Duffy Jul 27 '21 at 11:28