Running a script through shellcheck.net I was told that "for
loops over find
output are fragile." Fair enough, filenames with spaces are always tricky.
The suggested replacement code (one of them anyway) was this:
while IFS= read -r -d '' file
do
#do stuff
done < <(find . -name '*' -print0)
I'm familiar with the <
operator used to input text from a file to a command, and clearly the results from find
are being fed into the loop. So when I first saw this, I thought it was victim to some formatting problems and tried "cleaning up" the last line. But removing the whitespace between < <
resulted in syntax errors, as did adding one into <(
.
So what is the < <(cmd)
construct doing? Apologies if this is a simple or redundant question, it's not easy to search for these things!
The <
is input redirection as you say.
The <(
is Process Substitution.
Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of
<(list)
or
>(list)
The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form is used, the file passed as an argument should be read to obtain the output of list. Note that no space may appear between the < or > and the left parenthesis, otherwise the construct would be interpreted as a redirection.
When available, process substitution is performed simultaneously with parameter and variable expansion, command substitution, and arithmetic expansion.
You can't combine the two <
marks because then that becomes a here document token.
You can't add a space between <
and (
because then it stops being the process substitution token.
A while
loop in bash
is an example of a compound command. Like any other command, it has its own standard input. It doesn't actually read from it at all, but any command run from within the while
loop will inherit its standard input from the loop.
In this example, the read
command will read from the output of the find
command.
<(find ...)
is an example of process substitution. The find
command is run, and the <(...)
is treated like a file whose contents are the output of the find
command. It is this "file" that the while
loop (and therefore read
) uses for its standard input.
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