Some thougts about pipes

by Christian Franke <nobody-at-nowhere-dot-ws>

In a posix shell you can easily redirect input and output of a program, which is possibly one of the reasons for its power:

$ grep dhcp /var/log/daemon.log > dhcp.log

Here, we simply redirect stdout to a file. We can also just redirect stderr:

$ make 2> build.err

Here, we instruct our shell to write all errors encountered in the build process out to build.err by telling it to redirect fd 2 (stderr) to the file. If we want a full build log containing the normal output and the errors, we can use yet another operator:

$ make &> build.log

What may come as a suprise is that this operator is not known to the posix shell. It is neat for many situations, and implemented in many shells, but if you try to write somewhat portable shell scripts, you should probably refrain from using it, as it may be parsed as

$ make & > build.log

backgrounding the program and not redirecting stderr at all. There is a posix compliant replacement to redirect both stdout and stderr:

$ make > build.log 2>&1

As a note here, the order of the two redirection instructions is quite important. If you switch them around, you won't get the intended behaviour. It may help to think of the redirections not in terms of "redirect stdout to build.log" but to think of it as "open build.log and store the reference in stdout". The latter incantation emphasizes that the redirections are assignments internally and this is why order matters. If you issued

$ make 2>&1 > build.log

what would happen is that your shell would assign the current object of stdout to stderr in the first redirection and then store a reference to build.log in stdout in the second redirection. But now, stderr doesn't contain a reference to the file (which is the intention) but it contains the original stdout object, and so, error messages will probably print to your terminal than rather to the file.