bash: print stderr in red color

Solution 1:

command 2> >(while read line; do echo -e "\e[01;31m$line\e[0m" >&2; done)

Solution 2:

Method 1: Use process substitution directly:

command 2> >(sed $'s,.*,\e[31m&\e[m,'>&2)

Method 2: Create a function in bash or zsh :

color()(set -o pipefail;"$@" 2> >(sed $'s,.*,\e[31m&\e[m,'>&2))

Use it like this:

$ color command

Both methods will show the command's stderr in red.

Keep reading for an explanation of how it works. There are some interesting features demonstrated by these commands. The first 3 bullet points only apply to Method 2. The rest apply to both methods.

  • color()... — Creates a bash function called color.
  • set -o pipefail — This is a shell option that preserves the error return code of a command whose output is piped into another command. This is done in a subshell, which is created by the parentheses, so as not to change the pipefail option in the outer shell.
  • "$@" — Executes the arguments to the function as a new command. "$@" is equivalent to "$1" "$2" ...
  • 2> >(...) — The >(...) syntax is called process substitution. Preceded by 2> , it connects the stderr of the main command to the stdin of the sed process inside the parentheses.
  • sed ... — Because of the redirects above, sed's stdin is the stderr of the executed command. Its function is to surround each line with color codes.
  • $'...' A bash construct that causes it to understand backslash-escaped characters
  • .* — Matches the entire line.
  • \e[31m — The ANSI escape sequence that causes the following characters to be red
  • & — The sed replace character that expands to the entire matched string (the entire line in this case).
  • \e[m — The ANSI escape sequence that resets the color.
  • >&2 — Shorthand for 1>&2, this redirects sed's stdout to stderr.

Solution 3:

You can also check out stderred:

Solution 4:

The bash way of making stderr permanently red is using 'exec' to redirect streams. Add the following to your bashrc:

exec 9>&2
exec 8> >(
    while IFS='' read -r line || [ -n "$line" ]; do
       echo -e "\033[31m${line}\033[0m"
function undirect(){ exec 2>&9; }
function redirect(){ exec 2>&8; }
trap "redirect;" DEBUG

I have posted on this previously: How to set font color for STDOUT and STDERR

Solution 5: