These work fine and do what they should (print the contents of the file foo):
cat <foo
while read line; do echo $line; done <foo
cat <(cat foo)
However this gives me a syntax error in zsh:
zsh$ while read line; do echo $line; done <(cat foo)
zsh: parse error near `<(cat foo)'
and bash:
bash$ while read line; do echo $line; done <(cat foo)
bash: syntax error near unexpected token `<(cat foo)'
Does anybody know the reason and maybe a workaround?
Note: This is obviously a toy example. In the real code I need the body of the while loop to be executed in the main shell process, so I can't just use
cat foo | while read line; do echo $line; done
You need to redirect the process substitution into the while loop:
You wrote
while read line; do echo $line; done <(cat foo)
You need
while read line; do echo $line; done < <(cat foo)
# ...................................^
Treat a process substitution like a filename.
bash
/zsh
replaces <(cat foo)
by a pipe (kind of file) having a name as /dev/fd/n
where n
is the file descriptor (number).
You can check the pipe name using the command echo <(cat foo)
.
As you may know, bash
/zsh
also runs the command cat foo
in another process. The output of this second process is written to that named pipe.
without process substitution:
while ... do ... done inputfile #error
while ... do ... done < inputfile #correct
same rules using process substitution:
while ... do ... done <(cat foo) #error
while ... do ... done < <(cat foo) #correct
Alternative:
cat foo >3 & while read line; do echo $line; done <3;
I can suggest only workaround like this:
theproc() { for((i=0;i<5;++i)) do echo $i; }
while read line ; do echo $line ; done <<<"$(theproc)"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With