【问题标题】:Piping find results into grep for fast directory exclusion管道查找结果到 grep 以快速排除目录
【发布时间】:2012-07-18 21:50:23
【问题描述】:

我成功地使用 find 创建了当前子目录中所有文件的列表,不包括子目录“缓存”中的文件。这是我的第一段代码:

find . -wholename './cach*' -prune -o -print

我现在希望将其通过管道传输到 grep 命令中。看起来应该很简单:

find . -wholename './cach*' -prune -o -print | xargs grep -r -R -i "samson"

... 但这会返回主要来自缓存目录的结果。我已经尝试删除 xargs 引用,但这正是您所期望的,在文件名的文本上运行 grep,而不是在文件本身上运行。我的目标是在任何没有缓存内容的文件中找到“samson”。

在这种情况下,我可能会通过使用双 grep 来解决这个问题,但我很好奇为什么这个单行代码会以这种方式运行。我很想听听关于在仍然使用这两个命令的同时修改它的方法的想法(因为这样做有速度优势)。

(这是在 CentOS 5 中,顺便说一句。)

【问题讨论】:

    标签: linux recursion find grep piping


    【解决方案1】:

    在 find 上使用 -exec 选项,而不是通过管道将它们传递给另一个命令。从那里您可以使用grep "samson" {} \; 在列出的每个文件中查找 samson。

    例如:

    find . -wholename './cach*' -prune -o -exec grep "samson" "{}" +
    

    【讨论】:

      【解决方案2】:

      wholename 匹配可能是它仍然包含“缓存”文件的原因。如果您在包含“缓存”文件夹的目录中执行find 命令,它应该可以工作。如果不是,请尝试将其更改为 -name '*cache*'。

      此外,您的grep 不需要-r 或-R,这告诉它递归遍历目录 - 但您正在测试单个文件。

      您可以使用管道版本或单个命令更新您的命令:

      find . -name '*cache*' -prune -o -print0 | xargs -0 grep -il "samson"
      

      或

      find . -name '*cache*' -prune -o -exec grep -iq "samson" {} \; -print
      

      注意,第一个命令中的-l 告诉grep“列出文件”而不是匹配的行。第二个中的-q 也是如此;它告诉grep 安静地响应,所以find 将只打印文件名。

      【讨论】:

      • 谢谢!消除递归对我来说是诀窍。 (旧习惯很难改掉。顺便说一句,这是我打错了,因为我通常使用“-r -i -I”,这比冗余递归标志更有意义。)“wholename”部分很好,因为不需要的子目录确实位于当前目录的根级别。现在是:find . -wholename './cach*' -prune -o -print | xargs grep -i -I "samson"
      • 太棒了,很高兴这很简单 =]
      【解决方案3】:

      您已经告诉 grep 自身进行递归(两次!-r 和 -R 是同义词)。由于您传递的参数之一是 .(顶级目录),grep 正在每个文件中搜索(其中一些文件搜索两次,如果它们在子目录中,甚至更多)。

      如果您要使用find 和grep,请执行以下操作:

      find . -path './cach*' -prune -o -print0 | xargs -0 grep -i "samson"
      

      使用-print0 和-0 使您的脚本即使在文件名包含空格或标点符号的情况下也能正常工作。

      但是,您可能不需要在这里打扰find,因为 GNU grep 能够排除目录:

      grep -R --exclude-dir='cach*' -i "samson" .
      

      (这也排除了./deeply/nested/directory/cache。如果您只想排除顶层的缓存目录,请像以前一样使用find。)

      【讨论】:

      • 如果当前文件夹/路径中有太多文件,则单个 grep 将返回“参数过多”错误 - 因此您需要自己小心处理。
      • 感谢收看这个!正如“已接受”的答案中所述,立即清理已修复的问题。你们太棒了。
      • @newfurniturey 不,如果命令行太长(例如,如果我写了grep … * 并且有很多文件),shell 会出现“参数过多”错误.这里没有 shell globbing,命令行正好是 43 个字符。
      猜你喜欢
      • 1970-01-01
      • 2016-08-22
      • 2020-06-10
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      • 2012-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多