SittingBull SittingBull - 4 months ago 10
Linux Question

"cat a | cat b" ignoring contents of a

The formal definition of pipe states that the STDOUT of the left file will be immediately piped to the STDIN of the right file.I have two files,

hello.txt
and
human.txt
.
cat hello.txt
returns
Hello
and
cat human.txt
returns
I am human
.Now if I do
cat hello.txt | cat human.txt
, shouldn't that return
Hello I am human
?Instead I'm seeing
command not found
.I am new to shell scripting.Can someone explain?

Answer

Background: A pipe arranges for the output of the command on the left (that is, contents written to FD 1, stdout) to be delivered as input to the command on the right (on FD 0, stdin). It does this by connecting the processes with a "pipe", or FIFO, and executing them at the same time; attempts to read from the FIFO will wait until the other process has written something, and attempts to write to the FIFO will wait until the other process is ready to read.


cat hello.txt | cat human.txt

...feeds the content of hello.txt into the stdin of cat human.txt, but cat human.txt isn't reading from its stdin; instead, it's been directed by its command line arguments to read only from human.txt.

Thus, that content on the stdin of cat human.txt is ignored and never read, and cat hello.txt receives a SIGPIPE when cat human.txt exits, and thereafter exits as well.


cat hello.txt | cat - human.txt

...by contrast will have the second cat read first from stdin (you could also use /dev/stdin in place of - on many operating systems, including Linux), then from a file.

Comments