2

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

4

1 Answer 1

3

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.

14
  • 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? Commented May 7, 2018 at 7:51
  • that uses process substitution, but the stderr never seems to show up in the terminal Commented May 7, 2018 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
    Commented May 7, 2018 at 8:00
  • thanks, I asked a new question, because this one was a bit unclear: unix.stackexchange.com/questions/442250/… Commented May 7, 2018 at 8:07
  • nice sed prepending trick by the way, i didn't know that you could do that Commented May 7, 2018 at 8:08

You must log in to answer this question.

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