0

I have this command which works great

find . -type f -name *.txt -exec grep -li blah {} \;

Let's say the output will be:

/tmp/folder1/file1.txt
/tmp/folder2/myfile.txt
/tmp/thisfile.txt

If I was to do this:

find . -type f -name *.txt -exec grep -li -E --color blah {} \;

this would highlight the entire string. So /tmp/folder1/file1.txt would be highlighted.

Can I get it to highlight only the filename? So file1.txt, myfile.txt, thisfile.txt will be highlighted and nothing else.

Is this even possible?

DavidPostill
  • 153,128
  • 77
  • 353
  • 394

2 Answers2

3
$ find --version
find (GNU findutils) 4.7.0

So, find does not do \x1b or \e, then let us help...

$ find -type f -maxdepth 2 -printf "%h/§[1m%f§[m\n" | sed -re 's/§/\x1b/g' 

In man find you will find(!) more of those %<character> thingies.
They define what you want to have printed.

Here %h prints the first portion of the path, and %f the last portion of it (which usually is the filename) ...

NOTED:

$ find -type f -maxdepth 2 -printf "%h/$(tput bold)%f$(tput sgr0)\n"

... this is "nicer" as it will be terminal-type agnostic (as long as tput, ncurses-bin is installed); as is:

$ find -type f -maxdepth 2 \  
-printf "%h/$(setterm --reverse on)%f$(setterm --reverse off)\n"

Ref: man termifo for "bold" and similar, or even man setterm (from util-linux) as a replacement for tput

Hannu
  • 8,740
  • 3
  • 21
  • 39
  • This answer is partial. The OP wants to colorize the output of `grep -l`. The answer can be fixed thanks to the fact `-exec` is also a test in `find` and `grep -q` works well in such test. `find -type f -maxdepth 2 -exec grep -qi blah {} \; -printf "%h/§[1m%f§[m\n" | sed -re 's/§/\x1b/g'` – Kamil Maciorowski Dec 20 '22 at 19:47
  • The answer might be considered "partial", yes - but brings to front *the main thing* asked for. Look, i saw the tree in the forest. – Hannu Dec 22 '22 at 19:27
  • I think GNU find supports `find -printf '\033'`. Or in Bash and others you could use `find -printf $'\x1b'` – ilkkachu Dec 25 '22 at 22:56
0

This is a general-purpose filter that highlights text from the last / in a line to the end of the line. If there is no / then the whole line will be highlighted. Trailing / characters are treated like non-/.

highlight() (
if [ -t 1 ] || [ "$1" = -f ]; then
   start="$(tput bold)"
   end="$(tput sgr0)"
   sed "s|[^/]*./*$|$start\\0$end|;t;s|.*|$start\\0$end|;"
else
   cat
fi
)

Examples:

  1. highlight <<EOF
    dir/dir/file
    dir/dir/
    dir/dir/////
    no-slash
    /
    .
    EOF
    
  2. find . | highlight
    
  3. grep -lr . | highlight
    

Notes:

  • The filter can take input from find, grep or anything. The filter does not rely on non-portable find -printf.

  • tput bold and such are not portable though. Adjust start= and end= to your needs.

  • Inside the sed code | is used as a delimiter for s. It's crucial not to have | from the expansion of $start or $end. Adjust to your needs. Remember s in sed can use almost any character as delimiter.

  • The filter tests if its stdout is a terminal. If not, it becomes cat (i.e. a no-op filter). You can force highlighting even to a non-terminal with highlight -f. Example:

    find . | highlight -f | head -n 3
    
Kamil Maciorowski
  • 69,815
  • 22
  • 136
  • 202