How to retain grep’s match highlighting when piping find into grep

findgrephighlightingpipeterminal

If I run grep foo bar.txt, grep highlights each occurrence of "foo" in bar.txt. But sometimes I want to use find to determine which files grep searches. So I do something like this:

find . -iname "*.abc" | xargs grep foo

Or this:

find . -iname "*.abc" -exec grep foo {} \;

In both cases, grep correctly finds occurrences of "foo" in the specified files, but the output has no highlighting whatsoever.

How can I keep using find to choose files for grep to search without losing highlighting?

I am running Gnome Terminal 3.4.1.1 on Ubuntu 12.04, with bash as my shell.

Best Answer

In both commands, the problem is that not grep but another command generates the actual output (xargs and find, respectively).

You can solve this by directly calling grep for each file name:

IFS=$'\n'
for FILE in $(find . -iname "*.abc"); do
    grep foo $FILE
done
unset IFS

Or as a one-liner:

IFS=$'\n';for FILE in $(find . -iname "*.abc");do grep foo $FILE;done;unset IFS

How it works:

  • IFS=$'\n' sets the internal field separator to the newline character (or spaces in file names will cause problems).

  • for FILE in $(COMMAND); do COMMANDS done loops through the files specified by COMMAND, sets the variable FILE to the current file and executes COMMANDS.

  • grep foo $FILE searches for foo in $FILE and sends the results directly to the screen.

  • unset IFS sets the internal field separator back to its default value (not needed in a script).

Related Question