按内容递归查找文件

按内容递归查找文件

我想按内容在源树中递归查找文件。我使用 grep 尝试了以下操作:

$ grep -rn printf | grep %s | grep bcm_errmsg\(rv\)

这会按我想要的方式返回每一行,但现在,我想获取每个匹配文件的文件名,所以我将其更改为:

$ grep -rn printf | grep %s | grep -l bcm_errmsg\(rv\)

但我没有打印文件名,而是只得到

(standard input)

打印到标准输出。如何修复此问题以获取每个文件名和路径(以sed在其上使用)?

我想要做的:查找每个printf包含以下行的文件%sbcm_errmsg(rv)然后将以下 sed 命令应用于找到的文件:

sed -i 's/%s/%d/g; s/bcm_errmsg(rv)/rv/g;'

答案1

我认为你把事情过于复杂化了。要foo在当前目录和子目录中的所有文件中查找字符串,只需运行

grep -r "foo" *

默认情况下,grep 输出匹配行,前面加上找到它的文件名。

以下将仅输出文件名,而不输出匹配行:

grep -rl "foo" *

答案2

按照@steeldriver的最初想法,你可以这样做:

egrep -rl '.*printf.*%s.*bcm_errmsg\(rv\).*' . | xargs -d '\n' sed -i '/printf/ s/%s/%d/; /printf/ s/bcm_errmsg(rv)/rv/'

答案3

grep -rlZP '(?=.*printf)(?=.*%s)(?=.*bcm_errstr\(rv\))' . |
xargs -r0 sed -i -e '
        /%s/!b
        /printf/!b
        /bcm_errstr(rv)/!b
        s/%s/%d/g;s/bcm_errstr(rv)/rv/g
'

我们首先运行一个递归目录。从当前目录扫描具有以下字符串的文件: printf、%s 和 bcm_errstr(rv) 位于同一行,但可能以任意顺序。grep帮助我们做到这一点的选项是:

  • -r=> 将递归地启动当前目录及以下目录中的所有文件。
  • -l=> 将列出符合条件的文件名,即所有 3 个字符串位于同一行。
  • -Z=> 所选文件名以空分隔(\0)而不是通常的换行符(\n),以便我们能够处理任何类型的文件名。
  • -P=> 启用 Perl 正则表达式引擎,从而我们能够使用前瞻来确定 3 个字符串是否存在于同一行中。

在管道的另一端,xargs正在等待接收文件名,以 \0 分隔。然后,它尽可能地将所有这些文件名提供给 sed 命令行。您已经从上一个问题中知道了 sed 命令,它在其中执行 subs。仅在同一行包含 3 个字符串的那些行上。

相关内容