0

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...

Thanks

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

cat <( echo hello; )
3
  • What exactly are you trying to do with >() process substitution here?
    – muru
    Commented Aug 13, 2018 at 4:43
  • May i know what are you trying to do... cating the result of echo?
    – Siva
    Commented Aug 13, 2018 at 5:22
  • I stripped down the context as much as possible. cat was supposed to read echo. Thanks Commented Aug 13, 2018 at 22:12

4 Answers 4

2

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;)
2
  • Option 2 did the trick. as @muru said, 'it only had the pipe open for reading, not writing' Thanks Commented Aug 13, 2018 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). Commented Aug 14, 2018 at 17:28
2

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)
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)
foo
...
openat(AT_FDCWD, "/dev/fd/63", O_RDONLY) = 3

And:

$ 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.)

1

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

klopklap
hopklopklap

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.

0

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.

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .