列出包含字符串但 *NOT* 包含另一个字符串的文件的 Unix 命令

Posted

技术标签:

【中文标题】列出包含字符串但 *NOT* 包含另一个字符串的文件的 Unix 命令【英文标题】:Unix Command to List files containing string but *NOT* containing another string 【发布时间】:2011-06-26 17:55:55 【问题描述】:

我如何递归地查看包含一个字符串但没有另一个字符串的文件列表?另外,我的意思是评估文件的文本,而不是文件名。


结论:

根据 cmets,我最终使用:

find . -name "*.html" -exec grep -lR 'base\-maps'  \; | xargs grep -L 'base\-maps\-bot'

这返回了带有“base-maps”而不是“base-maps-bot”的文件。谢谢!!

【问题讨论】:

最简单的方法是使用grep -l 列出匹配模式的文件,然后将其通过管道传送到grep -v 属于superuser.com Mikel:但是,它只会将文件名通过管道传递给另一个 grep,而后者又只能从这些文件名中过滤而不是文件内容。 我已经尝试过了,并且同意 Alan 的观点,即它只过滤文件名。因此,它并没有达到我希望的效果。 @Alan 你不能传递 grep 一个文件集,如果是这样,你不能传递一个基于另一个 grep 的文件集吗?这只是我想象的可能性,但如果有人知道怎么做,那就太棒了:D 【参考方案1】:

试试这个:

grep -rl <string-to-match> | xargs grep -L <string-not-to-match>

解释:grep -lr 使 grep 递归 (r) 输出包含 &lt;string-to-match&gt; 的所有文件的列表 (l)。 xargs 循环遍历这些文件,在每个文件上调用grep -Lgrep -L只会在文件不包含&lt;string-not-to-match&gt;时输出文件名。

【讨论】:

grep 字符串应该被引用还是转义?是的,也不是。 另外,有没有一种好方法可以通过仅包含 .html 文件来提高流程效率? @Matrym find . -name "*.html" -exec grep -l &lt;string-to-match&gt; \; | xargs grep -L &lt;string-not-to-match&gt; @chrisaycock 添加 R 并转义连字符,这看起来对吗?找 。 -name "*.html" -exec grep -lR 'base\-maps' \; | xargs grep -L 'base\-maps\-bot' 太棒了。太棒了太棒了。【参考方案2】:

在上面的答案中使用 xargs 是不必要的;你可以像这样实现同样的事情:

find . -type f -exec grep -q <string-to-match>  \; -not -exec grep -q <string-not-to-match>  \; -print

grep -q 表示安静运行,但返回一个退出代码,指示是否找到匹配项; find 然后可以使用该退出代码来确定是否继续执行其其余选项。如果-exec grep -q &lt;string-to-match&gt; \; 返回0,那么它将继续执行-not -exec grep -q &lt;string-not-to-match&gt; \;。如果它也返回 0,它将继续执行-print,打印文件名。

正如另一个答案所指出的,以这种方式使用find 比您只想搜索某种类型的文件的grep -Rl 具有主要优势。另一方面,如果您真的想搜索所有文件,grep -Rl 可能更快,因为它使用一个grep 进程对所有文件执行第一个过滤器,而不是为每个文件使用单独的grep 进程.

【讨论】:

【参考方案3】:

这些答案似乎与 BOTH 字符串匹配。以下命令应该会更好:

grep -l <string-to-match> * | xargs grep -c <string-not-to-match> | grep '\:0'

【讨论】:

【参考方案4】:

这是一个更通用的结构:

find . -name <nameFilter> -print0 | xargs -0 grep -Z -l <patternYes> | xargs -0 grep -L <patternNo>

此命令输出名称与&lt;nameFilter&gt; 匹配的文件(根据需要调整find 谓词),其中包含&lt;patternYes&gt;,但不包含&lt;patternNo&gt;

增强功能是:

它适用于包含空格的文件名。 它允许您按名称过滤文件。

如果您不需要按名称过滤(通常想考虑当前目录中的所有文件),您可以剥离find 并将-R 添加到第一个grep

grep -R -Z -l <patternYes> | xargs -0 grep -L <patternNo>

【讨论】:

【参考方案5】:

找到 . -maxdepth 1 -name "*.py" -exec grep -L "string-not-to-match" \;

此命令将获取同一目录下所有不包含“string-not-to-match”的“.py”文件。

【讨论】:

【参考方案6】:

匹配字符串 A 并排除出现在我使用的同一行中的字符串 B 和 C,并使用引号允许搜索字符串包含空格

grep -r <string A> | grep -v -e <string B> -e "<string C>" | awk -F ':' 'print $1'

说明:grep -r 递归过滤所有输出格式匹配的行

文件名:行

要从这些行中排除 (grep -v) 还包含 -e 字符串 B 或 -e 字符串 C 的行。awk 用于仅打印第一个字段(文件名),使用冒号作为字段分隔符 -F

【讨论】:

请为您的代码添加一点解释以获取更多信息。

以上是关于列出包含字符串但 *NOT* 包含另一个字符串的文件的 Unix 命令的主要内容,如果未能解决你的问题,请参考以下文章

kubernetes 正在运行但未列出工作节点

可以在外部阶段列出文件但不能访问其中的文件?

核心数据 NSEntityDescription.entityForName 返回 nil,但 managedObjectModel.entities 列出了实体

如何删除会话中的所有对象,但名称在指定向量中列出的对象除外

Apache 本地虚拟主机已列出但不起作用

sh 删除.gitignore中列出但仍在存储库中的文件