我正在尝试做类似的事情
vi `grep -Rl 'keyword'`
但我想支持文件名中的空格。
vi "`grep -Rl 'keyword'`"
做不是做我需要的事情,它将 grep 输出转换为单个参数,其中包含 \n 。
我试过
vi "`grep -Rl 'keyword'`| xargs"
虽然看起来更好,但结果仍然是单个参数(现在用空格而不是 \n)。
有没有好的方法可以做到这一点? Bash 很好,因为符合 POSIX 标准而加分。
附言。
我知道 -R 选项不适用于所有 grep 实现,并且 bash 对于``
.
答案1
使用find
:
find . -type f -exec grep -q 'pattern' {} \; -exec vi {} +
这将在当前目录中或当前目录下的每个常规文件中查找匹配的行pattern
。对于这些找到的文件,vi
将启动。
如果这些文件有几百个,vi
就会调用批量文件。更改-exec vi {} +
为对每个文件-exec vi {} \;
调用一次。vi
我们使用它grep -q
是因为我们实际上对 的输出根本不感兴趣grep
,只对它的退出状态感兴趣。
这将允许任何有效的 Unix 文件名,并且完全符合 POSIX 标准(递归则grep
不然)。
答案2
怎么样
grep -Rl 'pattern' | xargs -d '\n' vi
我不知道这个-d
选项是如何 POSIXy 的。
如果您有 GNU 工具,最好允许任何文件名:
grep -Rlz 'pattern' | xargs -0 vi
答案3
在 bash 中,假设没有太多匹配的文件名$(getconf ARG_MAX)
,则另一种选择是循环遍历 globstar 下的扩展**
并构建匹配的文件名数组:
shopt -s globstar
matching_files=()
for entry in **
do
[ -f "$entry" ] || continue
grep -q 'pattern' -- "$entry" && matching_files+=("$entry")
done
vi -- "${matching_files[@]}"
循环将查找当前目录及其下的非隐藏文件和目录;我们做的第一个测试是看看我们是否有一个纯文件。如果是这样,我们会grep
对其运行安静/静音以获得所需的模式。如果文件包含该模式,我们将其文件名添加到matching_files数组中。最后,我们vi
在数组中安全扩展的条目列表上运行。
如果您还想搜索隐藏文件和目录,请设置shopt -s dotglob
.