56

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.. Commented 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/… Commented Jun 17, 2017 at 19:31

5 Answers 5

90

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
  • 1
    which find should work? Commented 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. Commented Dec 14, 2011 at 15:49
  • 1
    @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. Commented Apr 29, 2016 at 2:43
  • As of 2016 OSX does appear to support -L Commented Mar 8, 2017 at 0:14
  • 1
    @DavidMoles oh wow, I must have misread that half a dozen times. Commented Mar 8, 2017 at 5:07
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. Commented Dec 16, 2011 at 7:49
  • @Gilles yes I agree with you. I have +1 his answer. Commented 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... Commented 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. Commented 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... Commented 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. Commented 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. Commented 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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.