要查找所有包含该单词的文件foo
以及其中包含该单词的文件bar
,我们可以使用
grep -Ilri foo . | xargs grep -i bar
(不区分大小写并排除二进制文件)...但是,如果文件路径类似于
/Users/myusername/Text Files
那么它就不起作用了,因为现在该xargs
部分变成了
grep -i bar /Users/myusername/Text Files
但实际上它需要是
grep -i bar "/Users/myusername/Text Files"
或者
grep -i bar /Users/myusername/Text\ Files
如何让它发挥作用? (在 macOS Monterey 上)。
答案1
如果您grep
支持 GNU 的-Z
/--null
选项以空字节分隔文件名(FreeBSD 仅支持长--null
变体),并且您xargs
支持使用空字节作为输入项分隔符的-0
选项(也有一些),您可以使用它们来处理文件名--null
安全地:
grep -Ilri --null foo . | xargs -0 grep -i bar
如果您的grep
和xargs
不支持这些非标准选项(但话又说回来,两者都不-r
是-I
标准的),您可以使用find
:
find . -type f -exec grep -Iiq foo {} \; -exec grep -iq bar {} \; -print
它查找从当前目录开始的文件,对于它找到的每个文件,运行grep
以确定它是否包含“foo”,如果包含,则grep
再次运行以确定它是否包含“bar”,如果包含,则打印其姓名。
这效率不高,但可以安全地工作。
答案2
要在任何 Unix 机器上使用强制 POSIX 工具“查找其中包含该单词的所有文件foo
以及其中的单词”(未经测试):bar
find . -type f -exec \
awk '
FNR==1 { x=y=0 }
{ $0 = tolower($0) }
/foo/ { x=1 }
/bar/ { y=1 }
x && y { hits[FILENAME]; nextfile }
END { for (fname in hits) print fname }
' {} +
或者如果您愿意:
find . -type f -exec \
awk '
FNR==1 { x=y=0 }
{ $0 = tolower($0) }
/foo/ { x=1 }
/bar/ { y=1 }
x && y && !seen[FILENAME]++ { print FILENAME; nextfile }
' {} +
在上面的两种情况下,我们使用nextfile
支持它的 awks 来提高效率,但也编写代码以确保即使在不支持它的 awks 中,我们也不会多次打印相同的文件名。
上面假设您不关心子字符串或正则表达式与字符串匹配的匹配。