How to Make Stdout and Stderr Output Be of Different Colors in Xterm or Konsole

Is it possible to make stdout and stderr output be of different colors in XTerm or Konsole?

Here's a solution that combines some of the good ideas already presented.

Create a function in a bash script:

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

Use it like this:

$ color command -program -args

It will show the command's stderr in red.

Keep reading for an explanation of how it works. There are some interesting features demonstrated by this command.

  • 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>&1 — Redirects the stderr of the command to stdout so that it becomes sed's stdin.
  • >&3 — Shorthand for 1>&3, this redirects stdout to a new temporary file descriptor 3. 3 gets routed back into stdout later.
  • 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.
  • 3>&1 — Redirects the temporary file descriptor 3 back into stdout.

Here's an extension of the same concept that also makes STDOUT green:

function stdred() (
set -o pipefail;
(
"$@" 2>&1>&3 |
sed $'s,.*,\e[31m&\e[m,' >&2
) 3>&1 |
sed $'s,.*,\e[32m&\e[m,'
)

Bash, how to visually distinguish stdout from stderr?

Well, a few options.
Easiest would be to use hilite.

Other options would include writing custom shell wrapper to colorize the input.

A few options are here (note, that they are pretty much xterm-specific).

Using colors with printf

You're mixing the parts together instead of separating them cleanly.

printf '\e[1;34m%-6s\e[m' "This is text"

Basically, put the fixed stuff in the format and the variable stuff in the parameters.

In linux, how can I test whether the output of a program is going to a live terminal or to a file?

isatty(int fd) will check whether the fd refers to a terminal or something else. It's part of unistd.h in the GNU C library.

Man page: http://linux.die.net/man/3/isatty

As an aside: if you want to read from a program using another program, but you want to fool isatty into thinking that your program is a human, there is a way to do that. You can use a pseudo-terminal (pty). This technique is used by expect, for example.

How do I output coloured text to a Linux terminal?

You need to output ANSI colour codes. Note that not all terminals support this; if colour sequences are not supported, garbage will show up.

Example:

 cout << "\033[1;31mbold red text\033[0m\n";

Here, \033 is the ESC character, ASCII 27. It is followed by [, then zero or more numbers separated by ;, and finally the letter m. The numbers describe the colour and format to switch to from that point onwards.

The codes for foreground and background colours are:

         foreground background
black 30 40
red 31 41
green 32 42
yellow 33 43
blue 34 44
magenta 35 45
cyan 36 46
white 37 47

Additionally, you can use these:

reset             0  (everything back to normal)
bold/bright 1 (often a brighter shade of the same colour)
underline 4
inverse 7 (swap foreground and background colours)
bold/bright off 21
underline off 24
inverse off 27

See the table on Wikipedia for other, less widely supported codes.


To determine whether your terminal supports colour sequences, read the value of the TERM environment variable. It should specify the particular terminal type used (e.g. vt100, gnome-terminal, xterm, screen, ...). Then look that up in the terminfo database; check the colors capability.

How to overwrite stdout in C

It's not manipulating stdout -- it's overwriting the characters which have already been displayed by the terminal.

Try this:

#include <stdio.h>
#include <unistd.h>
static char bar[] = "======================================="
"======================================>";
int main() {
int i;
for (i = 77; i >= 0; i--) {
printf("[%s]\r", &bar[i]);
fflush(stdout);
sleep(1);
}
printf("\n");
return 0;
}

That's pretty close to wget's output, right? \r is a carriage-return, which the terminal interprets as "move the cursor back to the start of the current line".

Your shell, if it's bash, uses the GNU Readline library, which provides much more general functionality, including detecting terminal types, history management, programmable key bindings, etc.

One more thing -- when in doubt, the source for your wget, your shell, etc. are all available.

how to get current terminal color pair in bash

The question was about the current color, not the cursor position.

Both are "nonstandard" (though the latter, cursor position report is implemented by anything which has a valid claim to "VT100 emulator").

However, xterm implements a set of escape sequences referred to as dynamic colors, which predate the ANSI color functionality. Those set the working colors including text foreground and background. I modified this in 2002 to allow an application to send the sequence with a "?" rather than a color to tell xterm to return the color value, e.g.,

OSC 1 1 ? ST

using the notation given in XTerm Control Sequences

Curses can_change_color() always returns False

can_change_color() actually reports whether colors can be remapped, via init_color() -- an uncommon capability -- not whether colors can be used at all, via init_pair(). To check for that basic color capability, what you want is has_colors().

init_color(), on the terminals where it works, lets you do things like tweak the exact shade of blue used -- or make the terminal's idea of "blue" show up as something else entirely.



Related Topics



Leave a reply



Submit