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

741

如何使用 grep 命令查找当前目录中不包含单词 foo 的文件?

18个回答

3
当您使用find命令时,有两种基本选项:在find搜索完成后过滤结果或使用一些内置选项来防止find考虑与某个给定模式匹配的文件和目录。
如果您在大量文件和目录上使用前一种方法,那么您将使用大量CPU和RAM仅将结果传递给第二个进程,而第二个进程将再次使用大量资源过滤结果。
如果您使用-not关键字作为find参数,那么您将避免考虑任何路径与-name或-regex参数后面的字符串匹配,这将更加高效。
find . -not -regex ".*/foo/.*" -regex ".*"

然后,任何没有被-not过滤掉的路径都将被后续的-regex参数捕获。


这是在搜索不包含特定模式的文件名,对吗?我认为 OP 的意思是搜索不包含特定模式的文件内容。 - codeling
嗯,这个问题本身有点模糊,我只是这样解释的。当人们想要排除文件名时,一些人肯定会找到这个线程。 - Daniel J.

1
我的grep没有任何-L选项。我找到了实现这一点的解决方法。
这些想法是:
  1. to dump all the file name containing the deserved string to a txt1.txt.
  2. dump all the file name in the directory to a txt2.txt.
  3. make the difference between the 2 dump file with diff command.

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

我忘记了具体的命令,但你可以在两个输出流之间执行diff(我认为你需要在命令中加上括号,可能还有一个尖括号之类的符号)。如果你的系统支持这种方式,那就没有问题。但问题是它不支持grep -L - Dexygen

1

未解决的Bug报告

根据@tukan的评论,关于-L/--files-without-matches标志,Ag存在一个未解决的Bug报告:

由于该Bug报告进展缓慢,下面提到的-L选项不应被依赖,除非该Bug已经得到解决。请使用本主题中介绍的其他方法。以下是该Bug报告的一条评论[强调我的]:

有任何更新吗?-L完全忽略文件第一行的匹配。如果这个问题不能很快得到解决,那么这个标志应该被完全删除,因为它根本不按照广告所说的工作


The 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的错误,这有时会失败 - https://github.com/ggreer/the_silver_searcher/issues/238 - tukan
@tukan感谢您的迅速回复。我已经更新了答案,选择不删除答案,而是以有关错误的信息开头。 - dfrib

1

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

你可以在“find”下指定筛选器,在“grep -vwE”下指定排除字符串。如果需要按修改时间过滤,请在find下使用mtime。


这似乎显示了所有不包含该字符串的行,而OP要求仅显示文件名。 - Ben Farmer

1

当grep没有-L选项时(例如IBM AIX),还有另一种选择,只需使用grep和shell:

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

-3
这可能会对其他人有所帮助。我有一些混合了Gotest文件的文件。但是我只需要.go文件。所以我使用了
ls *.go | grep -v "_test.go"

-v,--invert-match 选择非匹配行 参见 https://dev59.com/KXA65IYBdhLWcg3w8zjt#3548465 还可以在vscode中使用此命令从终端打开所有文件
code $(ls *.go | grep -v "_test.go")

2
这将按名称而非内容过滤文件。 - Mathieu Longtin
@MathieuLongtin 是的,我明确说明了我有混合了Go文件和测试文件。但是我只需要.go文件。所以我使用了我只是添加这个来帮助其他人知道我使用的方法。 - ARIF MAHMUD RANA
2
你正在回答一个非常不同的问题。 - Mathieu Longtin

-6
grep -irnw "filepath" -ve "pattern"

或者

grep -ve "pattern" < file

以上命令将返回结果,-v用于查找被搜索模式的反向。


1
这将打印不包含该模式的行。您可以添加-l选项仅打印文件名;但是,这仍会打印包含任何不包含该模式的行的任何文件的名称。我认为OP想要找到不包含任何包含该模式的行的文件。 - tripleee
您提供的命令会列出“filepath”中所有文件的行,这些行都不包含“pattern”。 - aprodan

-7
下面的命令可以帮助你过滤包含子字符串"foo"的行。
cat file | grep -v "foo"

2
这将打印不匹配的行,而不是不包含任何匹配行的文件名称。更令人恼火的是,它还属于“无用的使用cat”(http://www.iki.fi/era/unix/award.html)。 - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接