Right now I have this:

 echo "$run_test" | bash 2>&1 | prepend "r2g-test:" "yellow";

What this does is prepend "r2g-test:" to each line of the stdout/stderr. Because I am sending stderr to stdout, the prepend program doesn't know the difference because it's all stdin to it.

Is there some way I can send stderr to a different prepend instance, perhaps with tee?

Perhaps something like this?

 echo "$run_test" | bash 2> $(prepend 'r2g-test:' 'red') | prepend 'r2g-test:' 'yellow';

This might work, with process substitution:

bash 2> >(prepend 'r2g-test:' 'red')

But so far, the stderr never shows up in the terminal


First, let's create a program run_test which generates both stdout and stderr:

$ run_test() { while sleep 0.2; do echo "Out $((++c))"; echo "err$c">&2; done; }

Now, let's send the stdout and stderr to different filters. Since I don't have a prepend installed, I will use sed for the same purpose:

$ exec 3>&2; { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

How it works

  • exec 3>&2

    This creates file descriptor 3 as a duplicate of stderr.

  • run_test | sed 's/^/stdout: /'

    This runs run_test and prepends stdout: to the beginning of stdout.

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3

    2>& redirects stderr to stdout so that stderr will go into the next pipe. 1>&3 redirects stdout to stderr so that it appears on the terminal.

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'

    The last pipe captures run_test's stderr, (which is now stdout) and prepends stderr: to it.

Using process substitution

$ run_test > >(sed 's/^/stdout: /') 2> >(stdbuf -oL sed 's/^/stderr: /' >&2)
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

The above uses stdbuf which is standard on Linux. For other OS's, one will need to look for analogous commands.

  • thanks! There must be a simpler way! I saw something like this using an intermediate fd, but I hoping for something less xrazy. What about this: echo "$run_test" | bash 2> >(prepend 'r2g-test:' 'red') | prepend 'r2g-test:' 'yellow'; ... why won't that work? May 7 '18 at 7:51
  • that uses process substitution, but the stderr never seems to show up in the terminal May 7 '18 at 7:52
  • 1
    @AlexanderMills I added a solution using process substitution. Note that anytime one one separates the two streams, output order is not guaranteed.
    – John1024
    May 7 '18 at 8:00
  • thanks, I asked a new question, because this one was a bit unclear: unix.stackexchange.com/questions/442250/… May 7 '18 at 8:07
  • nice sed prepending trick by the way, i didn't know that you could do that May 7 '18 at 8:08

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.