如何在Linux中一起查找包含两个字符串的文件?


11

我想查找包含两个字符串的文件,例如,文件包含string1string2

我想要输出中文件的完整路径。我不想看到“权限被拒绝”警告。

Answers:


15
grep -l string2 `grep -l string1 /path/*`

这与

grep -l string2 $(grep -l string1 /path/*)

编辑:这就是为什么grep string1 /path/* | grep string2不做我认为alwbtc想要的事情。

$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$

找不到任何内容,但文件b包含两个字符串。

这就是我认为alwbtc想要的

$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b

1
这是一个很好的解决方案,比我的解决方案更有用。对于那些想知道这里发生了什么的人(花了我一些时间来弄清楚),他正在使用该-l选项来返回文件名而不是行。然后,他使用美元符号或反引号将该列表作为FILE参数传递给第二个grep。这使第二个grep可以搜索找到的每个文件的整体,而不是像我的解决方案那样搜索单独的行。
Embedded.kyle

您错过了-l将两个命令视为相等的选项。
2013年

2

用管道grep输送到另一个管道:

grep "string1" /path/to/files/* | grep "string2"


5
如果两个字符串在文件中的不同行上,则将不起作用。
RedGrittyBrick 2012年

1
我不知道他们是否必须在同一行@RedGrittyBrick
slhck 2012年

@slhck:我已经更新了答案,以显示我认为alwbtc想要什么以及为什么这个答案没有做到这一点。当然,我可能会误解了alwbtc想要的东西,而Embedded.kyle可能做对了-我怀疑不是。
RedGrittyBrick 2012年

1

这是等效的 命令RedGrittyBrick的答案

ack string2 $(ack string1 -l)

以相同的方式工作(ack默认情况下,递归搜索当前目录除外)。$()搜索中的内容仅搜索找到该字符串的文件名,string1-l仅输出。然后将它们作为参数传递给外部命令,这意味着string2仅在这些文件列表中搜索。


0
comm -12 <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort) <(grep --fixed-strings --files-with-matches "STRING1" /path/to/files/* 2>/dev/null | sort)

或更少的冗余:

search_files () { str="$1"; shift; grep -Fl "$str" "$@" 2>/dev/null | sort; }
comm -12 <(search_files "STRING1" /path/to/files/*) <(sf "STRING2" /path/to/files/*)

如果字符串在同一文件的不同行上,则将起作用;如果文件名包含字符串之一,则也将避免误报。


0

要详细说明@RedGrittyBrick的解决方案,该解决方案在运行无人值守命令时存在一个缺点,并且可以按预期抑制错误输出并以递归方式查找文件

grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)

-s选项将禁止显示错误消息
-r选项允许在任意嵌套的目录中搜索字符串,
!&& echo /dev/null保证命令不会挂断。否则,如果inner grep找不到任何文件,它将不会输出任何内容,因此outer grep将会无限期等待搜索输入。/dev/null在这种情况下,此解决方案将输出,因此outer grepSTRING1/dev/null应该找不到任何内容的位置进行搜索。


0

我一直在寻找一种可扩展的方式来处理2个或更多字符串,并提出了以下建议:

grep -rl string1 path-to-files | xargs grep -l string2 | xargs grep -l string3

第一个grep递归地查找包含string1在中的文件的名称path-to-files

结果通过管道传输到xargs,以便在的那些文件上运行一个或多个grep命令string2

然后将结果通过管道传递到另一个xargs命令中string3-与第一个xargs调用相同,只是在寻找不同的字符串。

使用xargs将会避免出现太多结果的问题,以至于使用反引号引起的命令行太长。

为了避免警告,我们可以重定向stderr/dev/null

grep -rl string1 path-to-files  2>/dev/null | xargs grep -l string2

后续的grep调用不需要它,因为string1已经在文件中找到了,因此已知权限是好的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.