特定文件类型中单词的递归 grep

pau*_*ler 7 command-line grep

我想要一个命令行命令来在文件系统中搜索特定单词的所有 shell 脚本,所以我在工作中四处询问并得到以下解决方案:

grep word `find / -name \*.sh 2>/dev/null`
find / -name "*.sh" 2>/dev/null | xargs grep word
Run Code Online (Sandbox Code Playgroud)

但是,我对命令行不太熟悉,因此这两种解决方案对我来说似乎都不透明。我更喜欢做一些看起来像的事情:

ls -r *.sh | cat | grep -H word
Run Code Online (Sandbox Code Playgroud)

但是似乎您无法将文件名通过管道传输到 cat (至少我认为这就是问题所在)。

什么是最清晰的解决方案?其次,最有效的解决方案是什么?

编辑:我需要知道在哪个文件中找到了这个词,以便我可以修改脚本。

jw0*_*013 8

编辑:如果您有 GNU 实用程序,请参阅Gilles对使用 GNUgrep递归能力的方法的回答,该方法比该find方法简单得多。如果您只想显示文件名,您仍然需要添加-l我在下面描述的选项。


使用grep -l word仅打印包含匹配文件名。

如果要查找文件系统中所有以 结尾.sh、从根开始的文件/,那么find是最合适的工具。

最便携和最有效的建议是:

find / -type f -name '*.sh' -exec grep -l word {} + 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

这与它的可读性差不多,如果您了解每个组件背后的语义,则不难解析。

  • find /find从文件系统根目录开始运行,/
  • -type f: 只匹配常规文件
  • -name '*.sh': ... 并且只匹配名称以 .sh
  • -exec ... {} +:...在组中匹配的文件上运行指定的命令,其中{}由组中的文件名替换。这个想法是在系统限制内一次对尽可能多的文件运行命令 ( ARG_MAX)。{} +表单的效率来自...通过最大化传递给每次调用的文件数来最小化必须调用命令的次数...
  • grep -l word {}:与上面{}的相同{},并由文件名替换。如前所述,grep -l打印包含匹配的文件的名称word
  • 2>/dev/null:隐藏错误消息(从技术上讲,将标准错误重定向到黑洞/dev/null)。这是为了美观和现实的原因,因为在运行find/可能会导致你可能不关心,而您没有权限读取的文件和目录,你没有权限遍历“权限被拒绝”的消息的投注。

您在问题中收到和发布的建议存在一些问题。两个都

grep word `find / -name \*.sh 2>/dev/null
Run Code Online (Sandbox Code Playgroud)

find / -name "*.sh" 2>/dev/null | xargs grep word
Run Code Online (Sandbox Code Playgroud)

在名称中包含空格的文件上失败。最好避免将文件名完全放在命令替换中。第一个有可能遇到 ARG_MAX 限制的额外问题。第二个接近我的建议,但没有充分的理由在xargs这里使用,更不用说安全和正确使用 的xargs需要牺牲某些仅限 GNU 的选项的可移植性 ( find -print0 | xargs -0)。


Gil*_*il' 8

在非嵌入式 Linux、Cygwin 或其他带有GNU grep 的系统上,在FreeBSD 上,在NetBSDOSX 上

grep -r --include='*.sh' word .
Run Code Online (Sandbox Code Playgroud)

不要解析ls. 并且不要在 的输出上使用命令替换find,正如jw013 所解释的