11

Can someone please explain the difference between these two while loops:

while read test; do
echo $test
done <<< "$(seq 5)"

-

while read test; do
echo $test
done < <(seq 5)
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
HTF
  • 6,632
  • 6
  • 30
  • 49

2 Answers2

17
while read test; do
  echo $test
done <<< "$(seq 5)"

Execute seq 5, collecting the result into a temporary variable. Then execute the while loop, feeding it the collecting result.

while read test; do
  echo $test
done < <(seq 5)

Set up a subshell to execute seq 5 and connect its stdout to stdin. Then start the while loop. When it finishes, restore stdin.

What's the difference? For seq 5, practically nothing; however, it can still be made visible by changing seq 5 to seq 5; echo done generating sequence >&2. Then you can see that in the first case, the entire seq execution finishes before the while loop starts, while in the second case they execute in parallel.

$ while read n; do echo $n > /dev/stderr; done \
>       <<<"$(seq 5; echo done generating sequence >&2)"
done generating sequence
1
2
3
4
5
$ while read n; do echo $n > /dev/stderr; done \
>       < <(seq 5; echo done generating sequence >&2)
1
2
done generating sequence
3
4
5

If it were seq 10000000, the difference would be much clearer. The <<<"$(...) form would use a lot more memory in order to store the temporary string.

rici
  • 234,347
  • 28
  • 237
  • 341
4

Based on what I perceive, the only difference is that process substitution would represent a named pipe e.g. /dev/fd/63 as a file for input whereas <<< "" would send the input internally as if reading a buffer. Of course is the command reading the input is on another process like a subshell or another binary, then it would be sent to it like a pipe. Sometimes in environments where process substitution is not possible like in Cygwin, here documents or here strings along with command substitutions are more helpful.

If you do echo <(:) you see the difference in concept for process substitution over other string inputs.

Process substitution is more of representing a file, while here strings are more of sending in a buffer for input.

konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • 1
    Can you explain why `echo <(:)` prints a file in the form of `/dev/fd/`? Is `:` a special character? – jmrah Nov 05 '18 at 19:47
  • 2
    For posterity, the `:` character is an alias for the `true` command, and seems like the tersest way to demonstrate process substitution. More information about `:` at this SO answer: https://stackoverflow.com/a/3224910/2668666 – jmrah Dec 04 '18 at 13:31