What does "< <(command args)" mean in the shell?

20,663

Solution 1

<() is called process substitution in the manual, and is similar to a pipe but passes an argument of the form /dev/fd/63 instead of using stdin.

< reads the input from a file named on command line.

Together, these two operators function exactly like a pipe, so it could be rewritten as

find /bar -name *foo* -print0 | while read line; do
  ...
done

Solution 2

<( command ) is process substitution. Basically, it creates a special type of file called a "named pipe," then redirects the output of the command to be the named pipe. So for example, suppose you want to page through a list of files in an extra-big directory. You could do this:

ls /usr/bin | more

Or this:

more <( ls /usr/bin )

But NOT this:

more $( ls /usr/bin )

The reason for this becomes clear when you investigate further:

~$ echo $( ls /tmp )
gedit.maxtothemax.436748151 keyring-e0fuHW mintUpdate orbit-gdm orbit-maxtothemax plugtmp pulse-DE9F3Ei96ibD pulse-PKdhtXMmr18n ssh-wKHyBU1713 virtual-maxtothemax.yeF3Jo
~$ echo <( ls /tmp )
/dev/fd/63
~$ cat <( ls /tmp )
gedit.maxtothemax.436748151
keyring-e0fuHW
mintUpdate
orbit-gdm
orbit-maxtothemax
plugtmp
pulse-DE9F3Ei96ibD
pulse-PKdhtXMmr18n
ssh-wKHyBU1713
virtual-maxtothemax.yeF3Jo

/dev/fd/whatever acts like a text file with the output of the command between the parenthesis.

Solution 3

< redirects to stdin.

<() seems to be some sort of a reverse pipe, as mentioned on the page:

find /bar -name *foo* -print0 | \
while IFS= read -r -d $'\0' file; do
  dosomethingwith "$file"        # do something with each file
done

will not work, because the while loop will be executed in a subshell, and you'll lose changes made in the loop

Share:
20,663
stib
Author by

stib

I specialise in bespoke After Effects scripts and expressions, but my day gig also involves cinematography, animation, 3D, editing and futzing around with various flavours of code. I'm also particularly interested in long-term preservation of digital audiovisual media.

Updated on July 09, 2022

Comments

  • stib
    stib almost 2 years

    When looping recursively through folders with files containing spaces the shell script I use is of this form, copied from the internet:

        while IFS= read -r -d $'\0' file; do
          dosomethingwith "$file"        # do something with each file
        done < <(find /bar -name *foo* -print0)
    

    I think I understand the IFS bit, but I don't understand what the '< <(...)' characters mean. Obviously there's some sort of piping going on here.

    It's very hard to Google "< <" or "<(", you see. I tried "angle bracket parenthesis" and "less-than parenthesis" but didn't find anything.