查找包含多个字符串的文件

问题描述 投票:0回答:7

我使用命令递归查找包含特定

string1
的文件:

find . -type f -exec grep -H string1 {} \;

我需要查找包含多个字符串的文件,因此该命令应返回包含所有字符串的文件。像这样的东西:

find . -type f -exec grep -H string1 AND string2 {} \;

我找不到办法。字符串可以位于文件中的任何位置。即使只有两个字符串的解决方案也会很好。

string unix search grep find
7个回答
17
投票

你也可以试试这个;

find . -type f -exec grep -l 'string1' {} \; | xargs grep -l 'string2'

这显示包含 string1 和 string2 的文件名


6
投票

您可以链接您的操作,并使用第一个操作的退出状态,仅在第一个操作成功时才执行第二个操作。 (省略原色之间的运算符默认为

-and
/
-a
。)

find . -type f -exec grep -q 'string1' {} \; -exec grep -H 'string2' {} \;

第一个 grep 命令使用

-q
,“安静”,如果找到字符串,它会返回成功的退出状态。

要收集包含

string1
的所有文件,然后只需调用一次 grep 即可搜索
string2
,您可以使用
-exec ... {} +
:

find . -type f -exec grep -q 'string1' {} \; -exec grep 'string2' {} +

5
投票

与 GNU

grep

grep -rlZ 'string1' | xargs -0 grep -l 'string2'


来自

man grep

-r, --递归

按照符号递归读取每个目录下的所有文件 仅当它们位于命令行上时才链接。注意如果没有文件 给定操作数,grep 搜索工作目录。这是 相当于 -d 递归选项。

-Z,--null 输出零字节(ASCII NUL 字符),而不是通常跟在文件后面的字符 姓名。 例如,grep -lZ 在每个文件名后输出一个零字节,而不是通常的换行符。 此选项使输出明确,即使存在包含异常的文件名 像换行符这样的字符。 此选项可与 find -print0、perl -0、sort -z 等命令一起使用 和 xargs -0 来处理任意文件名,甚至包含换行符的文件名。


3
投票

惊讶于这个老问题缺乏明显简单的 Awk 解决方案:

find . -type f -exec awk '/string1/ && /string2/ { print; r=1 } END { exit 1-r }' {} \;

使用

r
变量的技巧只是模拟
grep
中的退出代码(零表示找到,1 表示未找到;如果您不在乎,可以将其删除)。

为了提高效率,也许从

-exec ... {} \;
切换到
-exec ... {} +
,不过你可能需要稍微重构一下 Awk 脚本(要么扔掉退出代码,要么更改它,以便退出代码指示“没有文件匹配”之类的内容) “仅部分文件匹配”与“所有文件匹配”?)

上面的代码查找在同一行包含两个字符串的文件。在任何线路上找到它们的情况都是一个简单的改变。

awk '/string1/ { s1=1 }
  /string2/ { s2=1 }
  s1 && s2 { print FILENAME; exit }
  END { exit(1 - (s1 && s2)) }' file

这只是打印文件的名称,并假设您有一个输入文件。对于处理多个文件,请稍微重构,以在访问新文件时重置

s1
s2
的值:

awk 'FNR == 1 { s1 = s2 = 0 }
  /string1/ { s1 = 1 }
  /string2/ { s2 = 1 }
  s1 && s2 { r=1; print FILENAME; nextfile }
  END { exit 1-r }' file1 file2 file3 ...

一些古老的 Awk 版本可能不支持

nextfile
,尽管它现在已在 POSIX 中。


1
投票

回答

正如您从本页的其他答案中看到的,有几种命令行工具可用于跨文件执行联合搜索。尚未发布的快速灵活的解决方案是使用ag:

ag -l string1 | xargs ag -l string2

有用的变化

对于不区分大小写的搜索,请使用

-i
:
ag

选项
ag -il string1 | xargs ag -il string2

对于其他搜索词,请扩展管道:

ag -l string1 | xargs ag -l string2 | xargs ag -l string3 | xargs ag -l string4

1
投票
grep -rlZ string1 | xargs -0 grep -l string2

如果您的模式是固定字符串,我们可以通过在 grep 中添加

-F
来加快命令速度:

grep -rlZF string1 | xargs -0 grep -lF string2

0
投票

这对我来说是最简单的(感谢 ChatGPT)。您可以添加任意数量的字符串

find /path/to/directory -type f -name '*string1*' -name '*string2*'
© www.soinside.com 2019 - 2024. All rights reserved.