38

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 :)

  • 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 '11 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 '17 at 19:31
8
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.

  • 4
    This is awfully complicated. See Kevin's answer. – Gilles Dec 16 '11 at 7:49
  • @Gilles yes I agree with you. I have +1 his answer. – Sachin Divekar Dec 16 '11 at 8:40
  • 5
    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... – don_crissti Oct 2 '15 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 '16 at 16:54
  • @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... – don_crissti Oct 13 '16 at 17:00
52

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 .
  • which find should work? – cwd Dec 14 '11 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 '11 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. – Rich Homolka Apr 29 '16 at 2:43
  • As of 2016 OSX does appear to support -L – David Moles Mar 8 '17 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). – David Moles Mar 8 '17 at 4:58
4

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
    That one has the benefit of being standard and portable. – Stéphane Chazelas Oct 2 '15 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. – Stéphane Chazelas Oct 2 '15 at 12:45
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.