【问题标题】:Unix Command to List files containing string but *NOT* containing another string列出包含字符串但 *NOT* 包含另一个字符串的文件的 Unix 命令
【发布时间】: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
  • Mikel:但是,它只会将文件名通过管道传递给另一个 grep,而后者又只能从这些文件名中过滤而不是文件内容。
  • 我已经尝试过了,并且同意 Alan 的观点,即它只过滤文件名。因此,它并没有达到我希望的效果。
  • @Alan 你不能传递 grep 一个文件集,如果是这样,你不能传递一个基于另一个 grep 的文件集吗?这只是我想象的可能性,但如果有人知道怎么做,那就太棒了:D

标签: linux command-line find command grep


【解决方案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

          【讨论】:

          • 请为您的代码添加一点解释以获取更多信息。
          猜你喜欢
          • 1970-01-01
          • 2014-05-25
          • 2012-11-21
          • 1970-01-01
          • 2011-08-31
          • 2023-03-26
          • 2013-04-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多