什么 Linux 命令可以查找包含某些字符串但不包含其他字符串的文件?

什么 Linux 命令可以查找包含某些字符串但不包含其他字符串的文件?

我尝试在大量 XML 文件中搜索某些字符串,但不搜索其他字符串,但无法组合命令来执行此操作。我只希望它列出符合包含/排除条件的文件名。我一直在尝试:

find . -name *.xml -exec grep -li "string1\|string2" {} \; | xargs grep -Li "string3\|string4"

但我遇到了麻烦,因为从寻找名字中有空格,第二个grep将它们全部分解成小块,当然找不到这样的文件。我尝试添加-0参数,它消除了错误,但它显示“文件名太长”并且只执行第一个 grep。

我如何调整此命令以使其在名称中带有空格的文件上正常工作?

答案1

有多种方法可以做到这一点。这应该将执行的进程总数保持在最低限度:

find . -name \*.xml -print0          \   # List of *.xml files (NUL-terminated)
  | xargs -0 grep -Zli 'string[12]'  \   # is input to first grep, which sends (NUL-term'd)
  | xargs -0 grep -Li  'string[34]'      # file list to second grep

谢谢马特·吉布森提醒我们-ZGNU grep 的标志。

答案2

你可以一次性完成所有操作find,这样可以避免文件名中出现空格的问题。例如

find . -exec grep -liq "string1\|string2" {} \; -not -exec grep -liq "string3\|string4" {} \; -print

“-q” 抑制所有 grep 输出。-exec当进程以 0 状态退出时,主进程返回 true,就像 grep 找到匹配项时所做的那样,而主-not进程会反转这一点。因此,我们直接在 上放置两个条件find,结果我们只打印满足这两个条件的文件名——无需管道!

答案3

正如我在评论中提到的那样,我认为您所缺少的是第一个 -Z 标志,grep以及您在尝试的 -0 xargs

find . -name "*.xml" -exec grep -liZ "string1\|string2" {} \; | xargs -0 grep -Li "string3\|string4"

答案4

如果限制因素是 CPU(即您的磁盘速度很快)并且您拥有更多 CPU 核心,则可以使用 GNU Parallel:

find . -type f| parallel grep -Lq foo {} '||' grep -l bar {}

通过立即运行这两个grep命令,文件可能仍在磁盘缓存中。如果磁盘寻道速度很慢,您可以添加-j1以禁用并行性。

观看介绍视频以了解更多信息:http://www.youtube.com/watch?v=OpaiGYxkSuQ

相关内容