37

When I run a program (for example grep or ls) without a pager, its output is colored. However when I run it piping its output to less, no colors are shown.

For example, this command outputs colored output:

grep -r something

but this doesn't:

grep -r something | less

Why? How can I see colors through less?

5
  • 7
    grep --color=always "search string" * | less -R but I tend to use most nowadays instead of less. ALSO: gnu.org/software/src-highlite is a color highlighter (less works too)
    – Rinzwind
    Jun 13, 2014 at 14:08
  • @alex have you installed python-pygments?
    – sourav c.
    Jun 13, 2014 at 14:09
  • @souravc no I did not install that Jun 13, 2014 at 14:11
  • @ales ignoring me are we? >:-D
    – Rinzwind
    Jun 13, 2014 at 14:21
  • Check here (or here) if what you want is just syntax highlight on less Mar 23 at 18:07

2 Answers 2

58

There are two problems here:

  • Commands like ls —which auto-detect the colour support— don't find support from pipes
  • less is set to just display colour codes by default.

Both can be overcome but it's a bit clunky:

ls --color=always | less -R

This isn't ls specific. Many commands that support colour also have an override argument.


A slightly more in-depth answer is that ls is checking whether or not its STDOUT belongs to a real terminal or not. When you pipe things around, the STDOUT is set to the STDIN of the next command.

You can see this at work in the ls source code. It's using the isatty command (a core POSIX interface) to work out what the situation is:

  • Are colours on by default:

        print_with_color = (i == color_always
                            || (i == color_if_tty
                                && isatty (STDOUT_FILENO)));
    
  • Do we try to output in multiple columns:

    if (format == long_format)
      format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);
    
    //...
    
    if (isatty (STDOUT_FILENO))
      {
        format = many_per_line;
        set_quoting_style (NULL, shell_escape_quoting_style);
        qmark_funny_chars = true;
      }
    else
      {
        format = one_per_line;
        qmark_funny_chars = false;
      }
    

grep does a very similar thing, unless explicitly overridden, it'll detect colour support, with isatty:

color_option = isatty (STDOUT_FILENO) && should_colorize ();
10
  • 1
    My last upvote (reached the limit) for today to support you for 100k. But me and Rinzwind want cake when that happens.
    – hytromo
    Jun 13, 2014 at 14:53
  • I downloaded a program with name was ack-grep. when type ack-grep foo , it will search for foo on the all sub directories.So I did ack-grep foo | less, and the colors gone. But seems this program does not support "--color=always", whatever thanks for help Jun 13, 2014 at 15:02
  • 2
    @alex ack has a --color argument: ack-grep -i select --color | less -R
    – Oli
    Jun 13, 2014 at 15:07
  • @Oli .........Oh my God........ the only thing that I can say about your knowledge and help and also power of linux Jun 13, 2014 at 15:53
  • 1
    @B1KMusic I agree. I agree so much that I found how how it works and updated the answer. You can force columns with a -C argument.
    – Oli
    Nov 19, 2015 at 9:47
4

If you're interested in colors in less more generally, you might want to look at lesspipe.sh. See, for example, https://github.com/wofr06/lesspipe.

lesspipe.sh is an input filter for the pager less as described in less's man page. The script runs under a ksh-compatible shell (e.g. bash, zsh) and allows you to use less to view files with binary content, compressed files, archives, and files contained in archives.

It will also colorize shell scripts, perl scripts, etc. similarly to a text editor, but without the use of any "preprocessing" program to do the colorizing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.