21

Is it possible to get colored output from the find command? That is, in the path of each found item, directories are blue, executable scripts are green, et cetera? I'm using version 4.4.2 of GNU findutils.

Edit - To clarify, each result would be highlighted like this:

./path/to/file.sh
  ^    ^  ^
  |    |  L green
   blue

(if, for example, executing find . -type f).

wes
  • 355
  • 1
  • 2
  • 5

7 Answers7

12

You could use -exec to do most of that (my solution doesn't color the directory part differently). If you have -print in your find command, replace it by -exec ls --color -d; if you're using the implicit printing, add that. This assumes your ls supports the --color option.

find . -exec ls --color -d {} \;
Tim Kennedy
  • 19,697
  • 1
    I'm not sure who upvoted this, but I don't believe they finished reading the question (not that I'm saying this answer deserves a corresponding downvote though)... – Ignacio Vazquez-Abrams Dec 08 '11 at 05:34
12

UPDATE: I've added a new (different) script... Ignacio Vazquez-Abrams had a point: The question really asks for executable scripts are green, et cetera.. okay... you'll find such a (prototype) script at the end of this answer.


This first (original) section is about grc and grcat.

This should work; grc... (as enzotib has pointed out.. The package name is grc ... The sub-utility used in the example, is grcat

generic colouriser for everything

generic colouriser, can be used to colourise logfiles,
output of commands, arbitrary text....
configured via regexp's.

The following example prints

  • ./ in magenta
  • bin/cpp/ in cyan
  • bigint in bold white

I haven't fully sorted out how it handles it config file yet, but this looks like it will do what you want (once you tame it).. eg. for a file with no sub-dir, and the color sequence seems to not be in the same sequence as the expressions.
I assume it is possible (but I'm a bit busy at the moment)...

echo "# my config file
regexp=(\./)(.*/)([^/]+)
colours=bold white,magenta,cyan
">$HOME/.grc/findhi

find . -maxdepth 3 -name '*' | grcat findhi

Here is the new Ignacio inspired script :)

This works if you use a single path as the first arg to find.
There are UNTESTED issues in this script. It is only concept.
One issue is: Symbolic Links... murky waters...
As-is, it prints an ERROR when it encounters an unknown type (eg. a symbolic link), and then continues processing past that.
Thanks to enzotib for the tput examples.

dircol=$(tput bold ;tput setaf 4)
coloff=$(tput sgr0)

root="$HOME"       # define path here, not in 'find` arg
root="${root:-.}"  # default to '.'
root="${root%/}/"  # add trailing '/'
#
find "$root" -maxdepth 1 -name '*' -printf "%y %P\n" | 
  while read -r line ;do
    case $line in 
       d   ) printf "%s\n" "$dircol$root$coloff";;  
       d\ *) printf "%s\n" "$dircol$root${line:2}$coloff";;  
       f\ *) l="$root${line:2}"
             d="${l%/*}/"
             f="${l##*/}"
             cd -P "$d" 
             printf "%s" "$dircol$d$coloff"  
             ls --color=always -R1 "$f"
             cd - >/dev/null
             ;; 
          *) printf "ERROR - type not yet catered for\n";;  
    esac
  done 
Peter.O
  • 32,916
  • You forgot to say you are referring to the grcat utility from the grc package :) At the beginning I had some difficulties to understand what you're saying. – enzotib Dec 08 '11 at 09:29
  • I really missed the fact that the OP want a different color for different types of files. – enzotib Dec 08 '11 at 14:52
  • Wow. Too much work to be worth it for me – Kellen Stuart Sep 22 '16 at 16:21
  • When I try to pipe find . -name "*$1*" -print 's output , I get following error message: ERROR - type not yet catered for – alper Jul 14 '20 at 16:25
  • grcat is the best colorizing tool I've found and I use it a lot, though even that's not perfect. Having a piped command at the end of a pipeline makes command line editing less convenient. – Sridhar Sarnobat Oct 21 '22 at 00:09
  • same problem as @enzotib, i found grc here, is this the correct one https://github.com/garabik/grc/blob/master/INSTALL? maybe edit your answer please to include that info. it looks too involved to add as a dependency for a file that you will share with multiple systems or other users... – Brian Thomas Feb 27 '24 at 21:41
6

This does only the two-color highlight for path and filename, not the per-filetype thing of ls:

Configure the colors of grep output in the right way for matched and unmatched part, and match the filename:

$ export GREP_COLORS="sl=0;33;49:ms=1;34;49"
$ find /etc/ -type f | head | grep --color=always '^\|[^/]*$'


screen-grep-colored

You may not want to overwrite the variable GREP_COLORS, so set it only for grep:

$ find /etc/ -type f | head | GREP_COLORS="sl=0;33;49:ms=1;34;49" grep --color=always '^\|[^/]*$'

(Definitions trom the deprecated variable GREP_COLOR have less priority than those in GREP_COLORS)

For the color codes, see colortest-16 from the package colortest,
and section "Set Graphics Rendition" in ANSI terminal command sequences.

Volker Siegel
  • 17,283
2

Another solution is fd which is...

... a simple, fast and user-friendly alternative to find. While it does not aim to support all of find's powerful functionality, it provides sensible (opinionated) defaults for a majority of use cases.

https://github.com/sharkdp/fd

fd demo

Beside the colorized output it has several nice features:

  • Intuitive syntax: fd PATTERN instead of find -iname '*PATTERN*'.
  • Regular expression (default) and glob-based patterns.
  • Very fast due to parallelized directory traversal.
  • Uses colors to highlight different file types (same as ls).
  • Supports parallel command execution
  • Smart case: the search is case-insensitive by default. It switches to case-sensitive if the pattern contains an uppercase character*.
  • Ignores hidden directories and files, by default.
  • Ignores patterns from your .gitignore, by default.
  • The command name is 50% shorter* than find :-).

In Debian and derivatives such as Ubuntu at least, it is called fdfind (name 75% longer than find :-)) because of a name clashing with another package.

phuclv
  • 2,086
0

I liked the -exec idea. I used it to create this function:

ff() {
    find . -name "$1" -exec ls -G -d {} +
}

-G is for FreeBSD ls (also found on Darwin or macos). For GNU or toybox (Android) ls, the equivalent is --color=auto.

SnIcK
  • 21
0

Extending on Peter O.'s answer:

You can add this function definition into your .bashrc or .bash_aliases.

(lr stands for list recursive, but you can name it however you want)

lr () { 
   dircol=$(tput bold ;tput setaf 4)
   coloff=$(tput sgr0)

case $# in 2) root=$2 depth=$1 ;; 1) root="." depth=$1 ;; 0) root="." depth=2 ;;
*) echo "Specify only upto 2 arguments: [depth [root folder]]" return ;; esac

root="${root%/}/" # add trailing '/'

find "$root" -maxdepth "$depth" -name '' -printf "%y %P\n" | while read -r line ; do case $line in d ) printf "%s\n" "$dircol$root$coloff";;
d\
) printf "%s\n" "$dircol$root${line:2}$coloff";;
f\ ) l="$root${line:2}" d="${l%/}/" f="${l##/}" cd -P "$d" printf "%s" "$dircol$d$coloff"
ls --color=always -R1 "$f" cd - >/dev/null ;; # l\
) printf "This is link.\n";; l\ ) l="$root${line:2}" d="${l%/}/" f="${l##/}"
cd -P "$d" printf "%s" "$dircol$d$coloff"
ls --color=always -d1 "$f" | tr -d '\n' printf " -> " readlink -f "$f" cd - >/dev/null ;;
) printf "ERROR - type not yet catered for\n";;
esac done }

This first parses the location and --maxdepth the find will work on, and then lists it with the colors.

It uses the arguments in the form [depth [root folder]]

Example uses:

lr 
lr 5
lr 2 Documents
0

If it's about colouring the files as ls does with --color (or -G on some BSDs) except for the path components leading to them to be coloured in blue+bold, then you could do:

find . -exec ls -q --color -d {} + |
  sed -E $'s|^((\e\[[0-9;]*m)*)(.*/)|\e[1;34m\\3\e[m\\1|'

(assuming a shell with support for ksh93-style $'...' quotes).

Where sed adds the blue+bold escape sequence (\e[1;34m .. \e[m) to the directory part.