Skip to content
Advertisement

“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?

Advertisement

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.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement