Simple process substitution with cat seems to hang:

cat >( echo hello; )

never finishes. Also tried:

cat >( echo hello; exit; )

Manually closing the standard out file descript from the subprocess does not work either:

cat >( echo hello; 1>&- )
cat >( echo hello; 1>&- exit; )

I have tried with GNU bash, version 4.4.23(1)-release, GNU bash, version 4.1.2(2)-release and zsh 5.5.1 (x86_64-debian-linux-gnu)

Can someone please explain why this is happening? I Really like process substitution...


Edit: If cat is to read from echo, the correct redirection in process substitution is:

cat <( echo hello; )

migrated from serverfault.com Aug 13 '18 at 4:12

This question came from our site for system and network administrators.

  • What exactly are you trying to do with >() process substitution here? – muru Aug 13 '18 at 4:43
  • May i know what are you trying to do... cating the result of echo? – msp9011 Aug 13 '18 at 5:22
  • I stripped down the context as much as possible. cat was supposed to read echo. Thanks – Francisco De Zuviria Aug 13 '18 at 22:12

Your code cat >( echo hola; ) will never get exit because,

  • it will first echo the pattern hola
  • And takes the input to write.
  • when we give Ctrl+D it keeps on searching the file to write.

Option 1: Write the context to a file which is echoed

cat > $( echo hola; )

so whatever the context we give below will be saved to file called hola.

Note: we can exit the cat block by Ctrl+D

Option 2: To cat the context which is echoed.

cat <(echo hola;)
  • Option 2 did the trick. as @muru said, 'it only had the pipe open for reading, not writing' Thanks – Francisco De Zuviria Aug 13 '18 at 22:11
  • No. "when we give Ctrl+D it keeps on searching the file to write" is wrong. cat never gets to see your ctrl-d. It waits for a ctrl-d on the /dev/fd/xx that is created as output-file by the >(echo hola). – Ljm Dullaart Aug 14 '18 at 17:28

I have no idea what you're trying to accomplish, but:

  1. >(...) makes the stdin of whatever is being run available for writing
  2. cat expects a file that can be read

There's no guarantee that whatever is provided by (1) can be read. On macOS, I just get an error:

bash-4.4$ cat >( echo foo)
cat: /dev/fd/63: Permission denied

On Linux, for me it's a pipe at the other end of which nothing is writing:

$ strace -e openat cat >(echo foo)
openat(AT_FDCWD, "/dev/fd/63", O_RDONLY) = 3


$ ll /proc/$(pgrep cat)/fd/3
lr-x------ 1 muru muru 64 Aug 13 18:55 /proc/3381/fd/3 -> 'pipe:[37501]'
$ lsof | grep 37501
strace    3433                 muru   63w     FIFO               0,12      0t0      37501 pipe
cat       3435                 muru    3r     FIFO               0,12      0t0      37501 pipe
cat       3435                 muru   63w     FIFO               0,12      0t0      37501 pipe

It doesn't matter that whatever was at the other end closed stdin and exited - it only had the pipe open for reading, not writing, and nothing was written to the pipe. So cat will remain there, waiting for the read to finish. (Both strace and cat here have an open file handle for writing to that pipe, but that's because bash opened it for writing and made it available for them. Neither are going to write to it.)


Process substitution is quite a subject of its own. The important part to realize is that it is more like a FIFO than stdin or stdout. You can see this with echo:

echo >( echo hello; )

gives you: /dev/fd/63 hello

The outer-echo gives you the argument that is actually given, which is /dev/fd/63. So, your

cat >( echo hello; )

is actually cat /dev/fd/43 and the output is sent to echo hello. (the 43 is just an example; the number is randomish, but often 63)

You can also see the difference between:

echo hop > >(cat)

which gives hop and

echo hop  >(cat)

which gives hop /dev/fd/63.

Also, as an example:

 sed 's/$/klap/' | tee >(sed 's/^/hop/')

which gives for the input klop


the klopklap is the stdout of tee and the hopklopklap is the stdout of the sed in the process substitution.

So why does cat >(echo hello) hang? Because, as said, cat gets an argument /dev/fd/32 and from that "file" it never gets an EOF.


The cat doesn't hang, it is waiting for your input. cat reads standard input and writes to standard output. You do not redirect the standard input, therefor standard input is your terminal. When you type Ctrl+D, you indicate End-of-File, and your cat will terminate.

  • i hope Ctrl+D will not work in this case, since Crtl+D looks for filename to write – msp9011 Aug 13 '18 at 5:35
  • I verified this myself, it's not that difficult to past the command into a shell. – RalfFriedl Aug 13 '18 at 5:37
  • Looks for the filename to write.. – msp9011 Aug 13 '18 at 5:38
  • Cat looks for file name to read. – RalfFriedl Aug 13 '18 at 5:39
  • even to write it need a file. – msp9011 Aug 13 '18 at 5:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.