31

If I do

$ ls -l --color=always

I get a list of files inside the directory with some nice colouring for different file types etc..

Now, I want to be able to pipe the coloured output of ls through grep to filter out some files I don't need. The key is that I still want to preserve the colouring after the grep filter.

$ ls -l --color=always | grep -E some_regex

^ I lose the colouring after grep

EDIT: I'm using headless-server Ubuntu 8.10, Bash 3.2.39, pretty much a stock install with no fancy configs

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
duckyflip
  • 16,189
  • 5
  • 33
  • 36

2 Answers2

53

Your grep is probably removing ls's color codes because it has its own coloring turned on.

You "could" do this:

ls -l --color=always | grep --color=never pattern

However, it is very important that you understand what exactly you're grepping here. Not only is grepping ls unnecessary (use a glob instead), this particular case is grepping through not only filenames and file stats, but also through the color codes added by ls!

The real answer to your question is: Don't grep it. There is never a need to pipe ls into anything or capture its output. ls is only intended for human interpretation (eg. to look at in an interactive shell only, and for this purpose it is extremely handy, of course). As mentioned before, you can filter what files ls enumerates by using globs:

ls -l *.txt      # Show all files with filenames ending with `.txt'.
ls -l !(foo).txt # Show all files with filenames that end on `.txt' but aren't `foo.txt'. (This requires `shopt -s extglob` to be on, you can put it in ~/.bashrc)

I highly recommend you read these two excellent documents on the matter:

yoniLavi
  • 2,624
  • 1
  • 24
  • 30
lhunath
  • 120,288
  • 16
  • 68
  • 77
  • 2
    As usual, shell coding on higher (and sane) levels. ++ – TheBonsai May 15 '09 at 11:15
  • @lhunath I never realized how bad such practice could be, thanks for the links and although I was using some advanced regex I will try and migrate that to glob and use natively inside `ls` – duckyflip May 15 '09 at 11:47
  • thanks for opening my eyes to this. I usually run "find" and see what comes up before I pipe the results to xargs – jpswain Jan 26 '11 at 23:08
  • 4
    @orange80: Don't pipe find(1) output to xargs(1). xargs is a broken tool since it tries to be "clever" and breaks your input filenames where there's whitespace and quotes. Nobody should ever use xargs (except for the rare case where you're using -0, which has almost always better alternatives). Instead, just use find's -exec command {} +. It does exactly the same thing as xargs, except, it doesn't rape your filenames (and you don't have the pipe + extra parsing + extra processes overhead). – lhunath Jan 27 '11 at 09:36
  • 1
    Nice. AFAIK is not possible to use glob for filtering symlinks like in this example: `ls -l --color=always /dev/disk/by-uuid/ | grep --color=never sda` – A.D. Oct 22 '14 at 20:59
  • @A.D. You _can_ filter symlinks with zsh glob patterns! `ls *(@)` lists all symlinks, and `ls *(^@)` lists all non-symlinks. – SilverWolf Sep 24 '18 at 03:29
0

You should check if you are really using the "real" ls, just by directly calling the binary:

/bin/ls ....

Because: The code you described really should work, unless ls ignores --color=always for some weird reason or bug.

I suspect some alias or function that adds (directly or through a variable) some options. Double-check that this isn't the case.

TheBonsai
  • 15,513
  • 4
  • 22
  • 14