我使用一个命令来递归查找包含特定string1的文件:
string1
find . -type f -exec grep -H string1 {} \;
我需要找到包含多个字符串的文件,所以命令应该返回那些包含所有字符串的文件。
find . -type f -exec grep -H string1 AND string2 {} \;
我找不到方法。字符串可以在文件中的任何地方。即使只有两个字符串的解决方案也会很好。
anhgbhbe1#
您还可以尝试以下操作;
find . -type f -exec grep -l 'string1' {} \; | xargs grep -l 'string2'
这将显示包含string 1和string 2的文件名
ulydmbyx2#
您可以链接您的操作,并使用第一个操作的退出状态,以便仅在第一个操作成功时执行第二个操作。(省略主操作之间的运算符默认为-and/-a。)
-and
-a
find . -type f -exec grep -q 'string1' {} \; -exec grep -H 'string2' {} \;
第一个grep命令使用-q“quiet”,如果找到该字符串,它将返回成功退出状态。要收集包含string1的所有文件,然后仅通过一次grep调用来搜索string2,可以使用-exec ... {} +:
-q
string2
-exec ... {} +
find . -type f -exec grep -q 'string1' {} \; -exec grep 'string2' {} +
cbjzeqam3#
使用GNU grep
grep
grep -rlZ 'string1' | xargs -0 grep -l 'string2'
从man grep开始-r,--递归递归地读取每个目录下的所有文件,如果符号链接在命令行中,则遵循这些符号链接。注意,如果没有给定文件操作数,grep将搜索工作目录。这等效于-d递归选项。-Z,--null输出零字节(ASCII NUL字符),而不是通常跟在文件名后面的字符。例如,grep -lZ在每个文件名后面输出一个零字节,而不是通常的换行符。此选项使输出明确,即使文件名包含换行符等不常见字符。此选项可与find -print 0、perl-0、sort -z和xargs -0来处理任意文件名,甚至是包含换行符的文件名。
man grep
pzfprimi4#
令人惊讶的是,这个老问题缺少显而易见的简单的Awk解决方案:
find . -type f -exec awk '/string1/ && /string2/ { print; r=1 } END { exit 1-r }' {} \;
使用r变量的技巧只是模拟grep中的退出代码(0表示找到,1表示没有;如果你不在乎,你可以把它拿出来)。为了提高效率,可以从-exec ... {} \;切换到-exec ... {} +,不过您可能需要对Awk脚本进行一些重构(或者丢弃退出代码,或者更改退出代码,使退出代码指示“no files matched”与“only some files matched”与“all files matched”?)上面的代码查找在同一行中包含两个字符串的文件。在任何行中查找它们的情况是很容易改变的。
r
-exec ... {} \;
awk '/string1/ { s1=1 } /string2/ { s2=1 } s1 && s2 { print FILENAME; exit } END { exit(1 - (s1 && s2)) }' file
这只是打印文件名,并且假设您只有一个输入文件。要处理多个文件,请稍微重构,以便在访问新文件时重置s1和s2的值:
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中。
nextfile
whlutmcx5#
答案正如您在本页的其他答案中所看到的,有几个命令行工具可用于执行跨文件的联合搜索。一个尚未发布的快速而灵活的解决方案是使用ag:
ag -l string1 | xargs ag -l string2
对于不区分大小写的搜索,请使用ag的-i选项:
ag
-i
ag -il string1 | xargs ag -il string2
对于其他搜索词,请扩展管道:
ag -l string1 | xargs ag -l string2 | xargs ag -l string3 | xargs ag -l string4
o8x7eapl6#
grep -rlZ string1 | xargs -0 grep -l string2
如果您的模式是固定字符串,我们可以通过在grep中添加-F来加快命令的执行速度:
-F
grep -rlZF string1 | xargs -0 grep -lF string2
6条答案
按热度按时间anhgbhbe1#
您还可以尝试以下操作;
这将显示包含string 1和string 2的文件名
ulydmbyx2#
您可以链接您的操作,并使用第一个操作的退出状态,以便仅在第一个操作成功时执行第二个操作。(省略主操作之间的运算符默认为
-and
/-a
。)第一个grep命令使用
-q
“quiet”,如果找到该字符串,它将返回成功退出状态。要收集包含
string1
的所有文件,然后仅通过一次grep调用来搜索string2
,可以使用-exec ... {} +
:cbjzeqam3#
使用GNU
grep
从
man grep
开始-r,--递归
递归地读取每个目录下的所有文件,如果符号链接在命令行中,则遵循这些符号链接。注意,如果没有给定文件操作数,grep将搜索工作目录。这等效于-d递归选项。
-Z,--null输出零字节(ASCII NUL字符),而不是通常跟在文件名后面的字符。例如,grep -lZ在每个文件名后面输出一个零字节,而不是通常的换行符。此选项使输出明确,即使文件名包含换行符等不常见字符。此选项可与find -print 0、perl-0、sort -z和xargs -0来处理任意文件名,甚至是包含换行符的文件名。
pzfprimi4#
令人惊讶的是,这个老问题缺少显而易见的简单的Awk解决方案:
使用
r
变量的技巧只是模拟grep
中的退出代码(0表示找到,1表示没有;如果你不在乎,你可以把它拿出来)。为了提高效率,可以从
-exec ... {} \;
切换到-exec ... {} +
,不过您可能需要对Awk脚本进行一些重构(或者丢弃退出代码,或者更改退出代码,使退出代码指示“no files matched”与“only some files matched”与“all files matched”?)上面的代码查找在同一行中包含两个字符串的文件。在任何行中查找它们的情况是很容易改变的。
这只是打印文件名,并且假设您只有一个输入文件。要处理多个文件,请稍微重构,以便在访问新文件时重置
s1
和s2
的值:一些古老的Awk版本可能不支持
nextfile
,尽管它现在在POSIX中。whlutmcx5#
答案
正如您在本页的其他答案中所看到的,有几个命令行工具可用于执行跨文件的联合搜索。一个尚未发布的快速而灵活的解决方案是使用ag:
有用的变化
对于不区分大小写的搜索,请使用
ag
的-i
选项:对于其他搜索词,请扩展管道:
o8x7eapl6#
如果您的模式是固定字符串,我们可以通过在grep中添加
-F
来加快命令的执行速度: