7

I have the following series of commands:

cd / && ls | ( cd /tmp && cat >dumpfile)

This series of commands does the following: it creates a file named /tmp/dumpfile. This file contains a listing of the root directory.

The cd / && ls output gets piped to a subshell. What I find odd is that in the subshell, instead of cd /tmp swallowing the ls output, the later cat >dumpfile gets it and writes it to a file. What is going on here?

2 Answers 2

8

The pipe sets up stdout to go from ls to the subshell.

In the subshell, cd /tmp and cat are done in the same process.

cd /tmp doesn't read from stdin (the pipe), so when cat reads from stdin, it gets all of ls's output.

3
  • Is it sufficient for the first command to have no process? What about ls | ( /bin/echo hi; /bin/cat ) which runs echo and cat as separate processes, but cat still reads stdin from ls instead of /bin/echo?
    – mrb
    Aug 17, 2012 at 13:31
  • If the first command is not a builtin, the shell will have to do an extra fork. But that doesn't matter, because children inherit their parents' file descriptors.
    – Mikel
    Aug 17, 2012 at 13:35
  • Thanks! To elaborate on your answer even further: I checked the cd's definition in IEEE Std 1003.1-2008. In the "STDIN" and "STDOUT" sections it says both streams are (almost always) not used by cd.
    – Abdull
    Aug 17, 2012 at 13:42
3

cd doesn't swallow the output because it doesn't want to. Consider this:

{ ls; date; } | (cd /tmp && date >> date.txt && cat date.txt && cat >dumpfile)

Only the last cat >dumpfile will save the stdin coming from the pipe, because none of the other commands want to consume it.

You must log in to answer this question.

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