如何查找不包含给定字符串模式的文件?


Answers:


817

如果您的grep具有-L(或--files-without-match)选项:

$ grep -L "foo" *

1
正如其他地方所指出的,ack默认情况下会避免使用.svn(Subversion)文件。
GuruM 2013年

11
@GuruM这可以通过导出变量GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git':^)在GNU grep中完成
bufh 2014年

6
或使用ag的等效项:ag -L 'foo'
主教

5
像魔术一样工作!提示:使用-rL而不是-L匹配子目录
Ufos

1
@Larry —避免出现问题的更干净的方法是使用“空”长选项,如下所示:grep -L 'foo' -- *标准是使用长选项的命令--用于指示此点之后没有更多选项。
帕迪·兰道

44

看一看ack。它会.svn自动为您执行排除操作,为您提供Perl正则表达式,并且只需下载一个Perl程序即可。

与您要查找的内容等效的是ack

ack -L foo

23

您可以单独使用grep来执行此操作(无查找)。

grep -riL "foo" .

这是对使用的参数的解释 grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

如果使用l(小写),您将得到相反的文件(带有匹配项的文件)

     -l, --files-with-matches
             Only the names of files containing selected lines are written

17

以下命令为我提供了所有不包含模式的文件foo

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

4
您想将grep 0的末尾更改为grep 0 $(否则,文件名中字符为0的文件将出现错误匹配)。
clouseau

9
@clouseau基本上是正确的...但是,grep '0$'也可以匹配10行倍数的文件!您需要grep ':0$'在末尾检查一个明确的“:0”。然后,您将只获得匹配零行的文件。
TrinitronX

我使用的UNIX没有带有这些选项的find或grep版本,因此我不得不使用其他注释中建议的“ ack”命令。
KC Baltz

14

以下命令排除了svn使用第二个查找来筛选出文件夹的需要grep

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

9

您实际上需要:

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

6

我祝你好运

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

我的尝试grep -v只是给了我所有没有“ foo”的限制。


4

问题

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

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

说明

管道前:

find . 从此目录开始递归查找文件

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

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

格列普

-H 始终使用输出行打印文件名标题。

-E 将模式解释为扩展的正则表达式(即,强制grep表现为egrep)。

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

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


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

$> 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

$> 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/..$//'去除每行的最后两个字符,仅保留文件路径。

$> 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

3

如果您使用的是git,它将搜索所有跟踪的文件:

git grep -L "foo"

并且可以在跟踪文件中的一个子集搜索,如果你有**子目录通配符打开(shopt -s globstar在.bashrc中,看到这个):

git grep -L "foo" -- **/*.cpp

1

我的grep没有任何-L选项。我确实找到解决此问题的方法。

这些想法是:

  1. 将包含应有字符串的所有文件名转储到txt1.txt中。
  2. 将目录中的所有文件名转储到txt2.txt中。
  3. 用diff命令区别2个转储文件。

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

我忘记了这些命令,但是实际上您可以diff在两个输出流之间进行a操作(我认为您在命令输出中用括号括起来,并且在某处也有尖括号),而不是转储文件名,如果您的系统支持的话,我想问题是,因为它不支持grep -L
Dexygen

1

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

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


这似乎向我显示了所有没有字符串的行,OP仅询问文件名。
本·法默

1

打开错误报告

正如@tukan所评论的那样,有一个关于-L/ --files-without-matches标志的针对Ag的公开错误报告:

由于错误报告的进展很少,因此,只要未解决该错误,就不要依赖-L下面提到的选项。请改用此线程中介绍的不同方法。引用有关错误报告的评论[强调我的]:

有任何更新吗?-L完全忽略文件第一行上的匹配项。好像这不会很快解决,应该将标记完全删除,因为它实际上不能像广告中那样工作


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

作为一种强大的替代方法grep,您可以使用The Silver Searcher-Ag

一个类似于ack的代码搜索工具,重点是速度。

查看man ag,我们找到-L--files-without-matches选项:

...

OPTIONS
    ...

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

即,要从当前目录中递归搜索不匹配的foo文件:

ag -L foo

要仅在当前目录中搜索不匹配的文件foo,只需指定--depth=0递归即可:

ag -L foo --depth 0

由于该-L错误,此操作有时会失败-github.com/ggreer/the_silver_searcher/issues/238
tukan

@tukan感谢您的提示。我已经更新了答案;选择不删除答案,而是打开有关该错误的信息。
dfri

1

当grep没有-L选项(例如IBM AIX)时,除了grep和shell之外什么也没有:

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

-4
grep -irnw "filepath" -ve "pattern"

要么

grep -ve "pattern" < file

上面的命令将为我们提供结果,因为-v查找正在搜索的模式的逆函数


1
这将打印不包含图案的行。您可以添加-l仅打印文件名的选项。但这仍会打印任何文件的名称,该文件包含不包含模式的任何行。我相信OP希望找到不包含任何包含模式的行的文件。
三人房

您提供的命令在“文件路径”中列出了所有不包含“模式”的行。
aprodan

-6

以下命令可以帮助您过滤包含子字符串“ foo”的行。

cat file | grep -v "foo"

2
这将打印不匹配的行,而不打印不包含任何匹配项的文件名。为了加重侮辱性伤害,这是对的无用用法cat
三胞胎
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.