关于grep:如何查找不包含给定字符串的文件?

How do I find files that do not contain a given string pattern?

如何找出当前目录中不包含单词foo(使用grep)的文件?


如果您的GREP有-L--files-without-match选项:

1
$ grep -L"foo" *


看看ack。它自动为您排除.svn,为您提供Perl正则表达式,并且是单个Perl程序的简单下载。

ack中,你所寻找的应该是:

1
ack -L foo


下面的命令给出了不包含模式foo的所有文件:

1
find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c "foo"  {} \; | grep 0


下面的命令不需要find通过使用第二个grep来过滤svn文件夹。

1
grep -rL"foo" ./* | grep -v"\.svn"

您实际上需要:

1
find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c "foo"  {} \; | grep :0\$

我很幸运

1
grep -H -E -o -c"foo" */*/*.ext | grep ext:0

我尝试使用grep -v时,所有的行都没有"foo"。


打开错误报告

正如@tukan所评论的那样,AG有一份关于-L--files-without-matches标志的开放性bug报告:

  • ggreer/银搜索者:238---files-without-matches工作不正常

由于bug报告进展不大,因此不应依赖下面提到的-L选项,只要bug尚未解决。请使用此线程中提供的不同方法。引用bug报告的注释[emphasis mine]:

Any updates on this? -L completely ignores matches on the first line of the file. Seems like if this isn't going to be fixed soon, the flag should be removed entirely, as it effectively does not work as advertised at all.

Silver Searcher-AG(预期功能-见错误报告)

作为grep的强大替代方案,您可以使用Silver Searcher-AG:

A code searching tool similar to ack, with a focus on speed.

man ag来看,我们发现-L--files-without-matches选项:

1
2
3
4
5
6
7
...

OPTIONS
    ...

    -L --files-without-matches
           Only print the names of files that don′t contain matches.

也就是说,从当前目录递归搜索不匹配foo的文件:

1
ag -L foo

要只搜索当前目录中与foo不匹配的文件,只需为递归指定--depth=0

1
ag -L foo --depth 0


find *20161109* -mtime -2|grep -vwE"(TRIGGER)"

您可以在"find"下指定过滤器,在"grep-vwe"下指定排除字符串。如果还需要过滤修改的时间,请使用"查找"下的mtime。


我的grep没有任何-l选项。我确实找到了解决办法。

这些想法是:

  • 将包含所需字符串的所有文件名转储到txt1.txt。
  • 将目录中的所有文件名转储到txt2.txt。
  • 使用diff命令对2个转储文件进行区分。

    1
    2
    3
    grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
    grep * *.log | cut -c1-14 | uniq > txt2.txt
    diff txt1.txt txt2.txt | grep">"

  • 问题

    我需要重构一个大型项目,该项目使用.phtml文件使用内联PHP代码编写HTML。我想用胡子模板代替。我想找到任何不包含字符串new Mustache.phtmlGiles,因为它们仍然需要重写。

    解决方案

    find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

    解释

    管道前:

    发现

    find .递归查找文件,从这个目录开始

    -iname '*.phtml'文件名必须包含.phtml(i使其不区分大小写)

    -exec 'grep -H -E -o -c 'new Mustache' {}'在每个匹配的路径上运行grep命令

    格雷普

    -H总是用输出行打印文件头。

    -E将模式解释为扩展的正则表达式(即force grep表现得像白鹭)。

    -o只打印行的匹配部分。

    -c只将选定行的计数写入标准输出。

    这将给我一个以.phtml结尾的所有文件路径的列表,其中包括每个路径中出现字符串new Mustache的次数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

    ./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
    ./app/MyApp/Customer/View/Account/studio.phtml:0
    ./app/MyApp/Customer/View/Account/orders.phtml:1
    ./app/MyApp/Customer/View/Account/banking.phtml:1
    ./app/MyApp/Customer/View/Account/applycomplete.phtml:1
    ./app/MyApp/Customer/View/Account/catalogue.phtml:1
    ./app/MyApp/Customer/View/Account/classadd.phtml:0
    ./app/MyApp/Customer/View/Account/orders-trade.phtml:0

    第一个管道grep :0$过滤此列表,仅包括以:0结尾的管道:

    1
    2
    3
    4
    5
    6
    $> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

    ./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
    ./app/MyApp/Customer/View/Account/studio.phtml:0
    ./app/MyApp/Customer/View/Account/classadd.phtml:0
    ./app/MyApp/Customer/View/Account/orders-trade.phtml:0

    第二个管道sed 's/..$//'去掉每行最后两个字符,只留下文件路径。

    1
    2
    3
    4
    5
    6
    $> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

    ./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
    ./app/MyApp/Customer/View/Account/studio.phtml
    ./app/MyApp/Customer/View/Account/classadd.phtml
    ./app/MyApp/Customer/View/Account/orders-trade.phtml

    1
    grep -irnw"filepath" -ve"pattern"

    1
    grep -ve"pattern" < file

    上面的命令将在-v找到要搜索的模式的反转时给出结果。


    下面的命令可以帮助您筛选包含子字符串"foo"的行。

    1
    cat file | grep -v"foo"