55

What concise command can I use to find all files that do NOT contain a text string?

I tried this (using -v to invert grep's parameters) with no luck:

find . -exec grep -v -l shared.php {} \;

Someone said this would work:

find . ! -exec grep -l shared.php {} \;

But it does not seem to work for me.

This page has this example:

find ./logs -size +1c  > t._tmp
while read filename
do
     grep -q "Process Complete" $filename
     if [ $? -ne 0 ] ; then
             echo $filename
     fi
done < t._tmp
rm -f t_tmp

But that's cumbersome and not at all concise.

ps: I know that grep -L * will do this, but how can I use the find command in combination with grep to excluded files is what I really want to know.

pss: Also I'm not sure how to have grep include subdirectories with the grep -L * syntax, but I still want to know how to use it with find :)

2
  • 1
    The first command you wrote worked fine on my computer. What version of find are you using? And since we're at it, maybe specify which unix you're running..
    – rahmu
    Dec 14, 2011 at 15:47
  • @rahmu, this command almost always does not work as you expect. You probably have had a very specific case. Please see unix.stackexchange.com/questions/339619/…
    – sgnsajgon
    Jun 17, 2017 at 19:31

5 Answers 5

89

Your find should work if you change -v -l (files that have any line not matching) to -L (files with no lines matching), but you could also use grep's recursive (-r) option:

grep -rL shared.php .
7
  • which find should work?
    – cwd
    Dec 14, 2011 at 15:13
  • @Kevin - sorry, find . -exec grep -v -l shared.php {} \; (and all the other variants I tried) is not working for me. I'm on OS X but I don't think that should matter. I gave you a +1 because I had forgotten about the -r option.
    – cwd
    Dec 14, 2011 at 15:49
  • @cwd i know this is old but i want to leave this here for future readers: the fact that you're on OS X does make a difference. Mac OSX uses FreeBSD commands. Most people here assume Linux (GNU) style commands. They have different arguments, different ways of handling details. Apr 29, 2016 at 2:43
  • As of 2016 OSX does appear to support -L Mar 8, 2017 at 0:14
  • @kevin I said it does, not that it doesn't. :) not that anyone explicitly said it didn't, but the comments were confusing (and I've certainly run into other OS X / BSD vs GNU issues). Mar 8, 2017 at 4:58
11
find . -type f | xargs grep -H -c 'shared.php' | grep 0$ | cut -d':' -f1    

OR

find . -type f -exec grep -H -c 'shared.php' {} \; | grep 0$ | cut -d':' -f1

Here we are calculating number of matching lines(using -c) in a file if the count is 0 then its the required file, so we cut the first column i.e. filename from the output.

6
  • 7
    This is awfully complicated. See Kevin's answer. Dec 16, 2011 at 7:49
  • @Gilles yes I agree with you. I have +1 his answer. Dec 16, 2011 at 8:40
  • 7
    This is not only "awfully complicated" but wrong as it would also list all files that contain a multiple of 10 lines matching the pattern. Even if that grep was fixed this would still assume no file names containing : or newline characters... Oct 2, 2015 at 11:46
  • @don_crissti, thanks for mentioning! Still, unless you use a lot of copy-paste code, the solution above is a rly nice gimmick.
    – Ufos
    Oct 13, 2016 at 16:54
  • 1
    @Ufos - I really don't get your comment... This is wrong. Anyway, feel free to use it if it looks like a "really nice gimmick" to you... Oct 13, 2016 at 17:00
6

I know that grep -L * will do this, but how can I use the find command in combination with grep to exclude files is what I really want to know

You could use find and grep like this:

find . -type f ! -exec grep -q 'PATTERN' {} \; -print

Here -print is executed only if the previous expression: ! -exec ... {} evaluates as true.
So for each file found, grep -q 'PATTERN' is executed, if the result is false then the entire expression ! -exec grep -q 'PATTERN' evaluates as true and the file name is printed.

2
  • 2
    That one has the benefit of being standard and portable. Oct 2, 2015 at 12:44
  • There's a difference with GNU's grep -L though in that it will also include the non-readable files in the list. Oct 2, 2015 at 12:45
2

You find not matching result by option -L

grep -iL shared.php .
-1

I think you are looking for a command like

find . -type f -execdir grep -q -v shared.php {} \; -print

The option -q makes grep quit and after using -execdir you need -print to print found files.

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .