I have very limited understanding about standard error and standard output...

One of the common methods is to redirect standard error to standard output. Does it mean that error (which usually goes to standard error) never goes to standard error anymore because redirection?

If that is true, is there any methods to duplicate standard error, redirect copy to standard output and let the original be directed to standard error as it was supposed to be?

  • 4
    There is no place for the language you've used in the previous versions of this post. Use appropriate language or do not use the site.
    – Jeff Schaller
    Oct 2, 2020 at 22:44

2 Answers 2


In my early days of Unix, it was explained to me that a pipe works just like plumbing.

A process basically has 3 connection points for your plumping:

          | pgm |
           |   |
      stdout   stderr

So, when you do cat | grep pattern, you get

        | cat |
   stdout|   |stderr
         |   \
    stdin|    \
     +------+  |
     | grep |  |
     +-+---++  |
 stdout|   |   |
       |   \__ |
       |      \|
       |       |stderr

(in those days, it was all ascii-graphics...)

When you redirect stderr to stdout, as in pgm 2>&1, the picture becomes:

    stdin |
       | pgm |
  stdout|   |stderr
        |   /
        |  /
        | /

In theory, you can do a lot of plumbing this way. For example: awk '{print;print > "/dev/stderr"}' copies stdin to both stdout and stderr.

However, it becomes quickly very confusing. See the bash manual for details.

NOTE: pgm = program in above diagrams.

EDIT: For fun, I tried a bit of more elaborate plumbing using simple shellscripts.


echoerr() { echo "$@" 1>&2; }
for i in 1 2 3 4 5 6 ; do
        echo "STDOUT $i"
        echoerr "STDERR $i"

and copytee.sh:

echoerr() { echo "$@" 1>&2; }
while read line; do
        echo "stdout $line"
        echoerr "stderr $line"

(note that copytee ads lower-case and generate adds uppercase)

To get in advanced forms of redirection, bash generate.sh 2> >(bash copytee.sh ) gives as output:

stdout STDERR 1
stderr STDERR 1
stdout STDERR 2
stderr STDERR 2
stdout STDERR 3
stderr STDERR 3
stdout STDERR 4
stderr STDERR 4
stdout STDERR 5
stderr STDERR 5
stdout STDERR 6
stderr STDERR 6

which is exactly what you asked for.


"Standard error" is not a specifically defined place. "Standard error" is whatever file descriptor 2 is attached to.

When you redirect "standard error" to "standard output", what you are doing is closing file descriptor 2, and then reopening it as a duplicate of file descriptor 1, so it becomes attached to whatever file descriptor 1 happens to be attached to at that moment. The original file descriptor 2 is lost (literally, the file descriptor is closed). So, you can not exactly do what you want to do. If you redirect "standard error" to somewhere else, file descriptor 2 is closed (and reopened to attach it to wherever you are redirecting to), and there is no longer any information about where it was "supposed to be".

  • Is "redirection" the only way to manipulate program output(file descriptor)? In wikipedia article about "file desctiptor" there are "clone()" "dup()", not sure if they are appropriate here, since I don't know anything about programming.
    – user435564
    Oct 2, 2020 at 19:27
  • 1
    Redirection is specifically shell terminology. dup() is a C library function. So it depends whether you wish to do this in a process you write yourself, or to any command run within a shell. Oct 2, 2020 at 20:28
  • I suspect any attempt to redirect stdout and stderr to the same file will mix up part-lines due to the different buffering on the two streams. The safe method would be to redirect stderr to an actual file, and send that to both stderr and stdout after the main program terminates. Oct 2, 2020 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy