我使用一个命令来递归查找包含特定 string1
的文件:
find . -type f -exec grep -H string1 {} \;
我需要查找包含多个字符串的文件,因此命令应该返回包含所有字符串的文件。类似这样:
find . -type f -exec grep -H string1 AND string2 {} \;
我找不到解决方法。这些字符串可能出现在文件的任何地方。即使是只针对两个字符串的解决方案也很好。
你也可以尝试这个;
find . -type f -exec grep -l 'string1' {} \; | xargs grep -l 'string2'
这显示包含字符串1和字符串2的文件名。
{}
包围起来,并使用 -d
参数来避免因带空格的文件名而出现错误,就像这样:find . -type f -exec grep -l 'string1' '{}' \; | xargs -d '\n' grep -l 'string2'
- snaut+
而不是 \;
结束 find 命令的 -exec
选项。这将使用单个 grep 命令尽可能多地搜索文件,减少运行的进程数量,从而获得更快的结果。 - Greg Barrett -and / -a 。)
find . -type f -exec grep -q 'string1' {} \; -exec grep -H 'string2' {} \;
第一个 grep 命令使用了 -q
,也就是“安静”模式,如果找到了字符串就返回成功的退出状态。
为了一次性使用 grep 收集所有包含 string1
的文件,并查找 string2
,可以使用 -exec ... {} +
。
find . -type f -exec grep -q 'string1' {} \; -exec grep 'string2' {} +
grep
grep -rlZ 'string1' | xargs -0 grep -l 'string2'
来自 man grep
-r, --recursive
递归读取每个目录下的所有文件,只有在命令行上指定了符号链接时才会跟随它们。请注意,如果未给出任何文件操作数,则grep搜索当前工作目录。这相当于-d递归选项。
-Z, --null 输出一个零字节(ASCII NUL字符),而不是通常跟随文件名的字符。例如,grep-lZ在每个文件名后输出一个零字节,而不是通常的换行符。此选项使输出明确无误,即使存在包含像换行符这样的不寻常字符的文件名称也是如此。此选项可与类似find-print0、perl-0、sort-z和xargs-0的命令一起使用,以处理任意文件名,甚至包含换行符的文件名。
很惊讶这个老问题缺乏明显简单的Awk解决方案:
find . -type f -exec awk '/string1/ && /string2/ { print; r=1 } END { exit 1-r }' {} \;
r
variable 是为了模拟 grep
的退出码(零表示找到,一表示未找到;如果您不关心,可以省略)。为了效率,可以从 -exec ... {} \;
切换到 -exec ... {} +
,尽管这样可能需要对 Awk 脚本进行重构(要么丢弃退出码,要么更改退出码以指示“没有匹配的文件”vs“只有一些文件匹配”vs“所有文件匹配”?)。以上代码查找同时包含两个字符串的文件。在任何行上找到它们的情况很容易改变。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标准。
从本页面的其他答案中可以看出,有几个命令行工具可用于在文件之间执行联合搜索。一个快速而灵活的解决方案是使用ag:
ag -l string1 | xargs ag -l string2
若要进行不区分大小写的搜索,请使用ag
的-i
选项:
ag -il string1 | xargs ag -il string2
为了获得更多的搜索结果,可以扩展管道:
ag -l string1 | xargs ag -l string2 | xargs ag -l string3 | xargs ag -l string4
grep -rlZ string1 | xargs -0 grep -l string2
-F
来加速处理:grep -rlZF string1 | xargs -0 grep -lF string2
egrep -l“string1|string2”
会给出包含string1
或string2
的所有文件,如果存在参数,则可以使用egrep -l“string1<parameter>string2”
来查找包含string1
和string2
的文件,这样就可以解决您的问题。(虽然我不知道是否存在这样的参数) - Dominique|
的并集运算符&
,但是没有常见的正则表达式工具实现它。简单的解决方法是使用awk '/pattern1/ && /pattern2/'
,因此已经有一种简单的方法来实现这一点,尽管不能使用grep
。 - tripleee