Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash wrapper to color stderr red

Tags:

bash

colors

Bash supports colors, i.e. \033[31m switches to red and \033[0m switches back to uncolored.

I would like to make a small bash-wrapper that reliably puts out stderr in red, i.e. it should put \033[31m before and \033[0m after everything that comes from stderr.

I'm not sure that this is even possible, because when two parallel processes (or even a single process) writes to both stdout and stderr there would have to be a way to distinguish the two by a character-by-character basis.

like image 515
Robby75 Avatar asked Mar 21 '26 17:03

Robby75


2 Answers

Colorizing text is simple enough: read each line and echo it with appropriate escape sequences at beginning and end. But colorizing standard error gets tricky because standard error doesn’t get passed to pipes.

Here’s one approach that works by swapping standard error and standard output, then filtering standard output.

Here is our test command:

#!/bin/bash

echo hi
echo 'Error!' 1>&2

And the wrapper script:

#!/bin/bash
(# swap stderr and stdout
 exec 3>&1 # copy stdout to fd 3
 exec 1>&2 # copy stderr to fd 1
 exec 2>&3- # move saved stdout on fd 3 over to 2
 "${@}") | while read line; do
                echo -e "\033[31m${line}\033[0m"
           done

Then:

$ ./wrapper ./test-command
hi
Error! # <- shows up red

Unfortunately, all output from the wrapper command comes out of stderr, not stdout, so you can’t pipe the output into any further scripts. You can probably get around this by creating a temporary fifo… but hopefully this little wrapper script is enough to meet your needs.

like image 103
andrewdotn Avatar answered Mar 24 '26 01:03

andrewdotn


Based on andrewdotn's wrapper

Changes:

  • Puts the stderr output back to stderr
  • Avoid echo -e processing content in the lines

wrapper

#!/bin/bash

"${@}" 2> >(
while read line; do
    echo -ne "\033[31m" 1>&2
    echo -n "${line}" 1>&2
    echo -e "\033[0m" 1>&2
done
)

Issues: The output lines end up grouped, rather than mixed stdout/stderr

Test script:

#!/bin/bash

echo Hi
echo "\033[32mStuff"
echo message
echo error 1>&2
echo message
echo error 1>&2
echo message
echo error 1>&2

Output:

Hi
\033[32mStuff
message
message
message
error # <- shows up red
error # <- shows up red
error # <- shows up red
like image 21
rrehbein Avatar answered Mar 24 '26 00:03

rrehbein



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!