tags:

views:

714

answers:

5

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

A: 

The ls command checks if it writes to a tty or to a pipe or file or other. If it writes to a terminal it makes sense to include formatting and colors else it does not (and in your case might interfere with your grep).

Maybe this hack will work (untested):

ls -l --color=always $(ls | grep -E some_regex)
Peter van der Heijden
I think your solution almost works, but when the $(..) returns the filenames for the main ls to list, if the file is a directory then it descends and lists the files inside the directory, which is not exactly what I want to do.
duckyflip
-1, Broken suggestion. You're parsing ls here which you should never do. The wordsplitting performed by bash on the output of ls|grep to try and make arguments off of it to feed to ls will cut the output apart anywhere there is whitespace. that leads to broken filenames that contain whitespace (spaces, tabs, newlines). Also, any glob metacharacters will expand. Filenames that contain question marks, stars, etc will cause horrible results here.
lhunath
@lhunath - You are right. Did not realize that when I posted. Thanks for commenting on the downvote.
Peter van der Heijden
@duckyflip - You are probably better off not using my suggestion. See lhuntah's comment. Having said that, if you want to prevent `ls` from descending into directories you can use the `-d` option. (I think, only MS systems around here, can't check)
Peter van der Heijden
A: 

I cannot reproduce this on CentOS 5.2 - colors stay after grep. Using GNU bash, version 3.2.25(1)-release (i686-redhat-linux-gnu)

Denys
A: 

Ditto on Denys' response for Cygwin on WinXp and Xubuntu Intrepid.

I do get a slightly similar problem whilst using a busybox version of grep, but that's because it isn't a complete gnu grep.

Are you using any particular cut-down version of grep?

Andy
A: 

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
+11  A: 

Your grep is probably removing ls' 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 output very stupid (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. You should never pipe ls into anything, and never capture its output. ls is ONLY ever 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:

lhunath
As usual, shell coding on higher (and sane) levels. ++
TheBonsai
+1, great explanation, and those are really good links!
Andy
@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