The Linux Page

Not losing the colors with "less" when doing a grep, ls, etc.

A bunch of fruits on a table with five smoothies

Unix in Colors

Whenever I run a command without piping it through less, I generally get colors.

This is true in this century that computer started to use more and more colors in the console. It's practical for all sorts of reasons.

However, you lose those nice colors when you want to use "less" to paginate the results. There are two reasons for that:

Terminal vs. Pipe

The fact is that many tools will check their stdout and determine whether it's a terminal or not. If not, it can generally be assumed that it's a file, a pipe, a variable, etc. and therefore a place where the color commands should not be sent because the next processing of the output would likely be badly affected by all the controls, square backet, and other terminal commands.

Actually, those commands are really very specific to the terminal and therefore should not be sent anywhere else. But of course, when you use less (or more) you are on the terminal so why not display the colors as expected?!

There are various potential problems, although frankly in generally this technique works great. So we do want to be able to print colors even to a pipe.

In case of the ls and grep commands, they both require the --color command line option for the color to stick even when the command gets piped:

ls --color
grep --color=always

Notice that for grep you need to use the "always" keyword. This is because it detects whether the output is a TTY or not. If it is, then it turns off the feature. You could create an alias, though that does it for you. For example:

alias grepc="grep --color=always"

Then you can use cgrep instead of grep to always get colors.

Check the manual page of other commands you'd like to keep the colors from as it is not unlikely that they have a similar color option.

The effect of the --color is to skip the test to know how to handle stdout. It will just always send the color.

For those interested in how this is done under Linux, you use the isatty() function. Somthing like this:

#include <unistd.h>
#include <string.h>

 // true only if stdout is a TTY
bool use_color = isatty(fileno(stdout));
...
if(strcmp(argv[idx], "--color") == 0)
{
    use_color = true; // force true
}
...

There are many other tests, but this gives you the basics. Specifically, the ls code tests whether the terminal actually supports colors. If not, it will again set the use_color parameter to false.

The command also lets you assign colors to the various types it supports so there is quite a bit more to do than just this one test. But you're on your own for that code!

Keep Colors in "less"

Interestingly enough less removes the terminal codes by default. I find that ideology strange especially thinking that a file could include terminal codes that you'd like to see interpreted by the terminal and not as control (such as "^[").

So in order to keep the colors, you must instruct less to display them as is. This is done with the "-r" command line option. The "-R" may work better in your circumstances.

So to paginate the output of ls in color with less, you write:

ls -l --color | less -r

Notice how the two sides need an additional command line option to make this  work. If you only use the --color or the -r.

With grep, you do the following:

grep --color=always alexis *.* | less -r

# with the alias as shown earlier:
grepc alexis *.* | less -r