我在 Linux Ubuntu 18.04 和 20.04 上。
Ripgrep ( rg
) 可以输出包含匹配的文件的路径列表,如下所示:
# search only .txt files
rg 'my pattern to match' -g '*.txt' -l
# long form
rg 'my pattern to match' --glob '*.txt' --files-with-matches
输出将是:
path/to/file1.txt path/to/file2.txt path/to/file3.txt
等等
然后我想在每个路径上运行另一个命令,例如tree $(dirname $PATH)
,以获取包含匹配文件的目录中所有文件的列表。我怎样才能做到这一点?
我觉得xargs
可能是答案的一部分?但是像这样开始的管道xargs
似乎只处理最后打印的文件:
rg 'my pattern to match' -g '*.txt' -l | xargs -0 -I {} dirname {}
注意:如果您也可以演示,grep
那么对于没有 的人也可能有用ripgrep
,尽管 ripgrep非常易于安装。
在 GNU 系统上,可能是这样的:
请注意,如果两者都
dir/file.txt
匹配dir/subdir/file.txt
,您最终会同时运行tree
anddir
,dir/subdir
因此您将看到dir/subdir
两次的内容。您有正确的想法,使用
xargs
which 是将字节字符串转换为要传递给命令的参数列表的命令,并使用-0
which 是传递任意参数列表的最可靠方法,但是:xargs -0
期望输入格式为参数列表由 NUL 字符(0 字节)分隔¹。您需要-0
/--null
选项才能rg
以该格式打印文件列表。dirname
每次调用可以处理多个参数,因此我们不使用-I{}
,而是将它们全部传递²。如果文件列表为空,我们还希望-r
根本不调用,并且(也是 GNU 特定的)选项为自己打印以 NUL 分隔的目录。dirname
-z
dirname
dirname
rg
不会./
为每个文件添加前缀,因此重要的是--
对我们将文件列表作为参数传递给的命令使用选项分隔符,以避免-
文件名中的前导 s 出现问题。简而言之,对于其值可以是任何非 NUL 字节序列(例如文件路径或任意命令参数)的列表,您希望使用 NUL 分隔的记录作为交换格式,以编程方式在工具之间传递列表,并且只保留人类格式向用户提供反馈的工具(这里是 的树状输出
tree
)。在非 GNU 系统上,但使用
zsh
shell,您可以:或者一口气(假设至少有一个匹配的文件):
(
u
foru
nique) 是替换typeset -U
.0
参数扩展标志是我们告诉zsh
在 NUL 上拆分的方式。或者,我们可以设置IFS=$'\0'
并依赖分词(在不带引号的参数扩展时完成):如果您既没有 GNU 实用程序也没有 GNU 实用程序
zsh
,您总是可以求助于perl
:¹这是唯一一个不能出现在命令参数中的字符/字节值(因为参数在
execve()
系统调用中作为 NUL 分隔的字符串传递),但它可以出现在通过管道馈送的字节流中,所以它很简单以及在那里分离任意参数的明显方法。-0
是 GNU 实现的非标准扩展xargs
,但现在在许多其他实现中都可以找到它² 或至少在一次调用中可以容纳的数量,
dirname
仅在需要时调用多次。更新:新的最终答案:
请注意,
sort -zu
对空分隔 (-z
) 列表中的重复项进行排序和删除。较早的答案详细信息:
请参阅此答案下方的评论。我在这里的回答不如@Stéphane Chazelas 的其他回答那么可靠。
我下面的答案最初不会正确处理任何带有空格或其他空格的文件名,也不会处理以破折号(
-
)开头的文件名。下面是我的回复评论:所以,看看这两个答案。他在技术上更好,但就我的目的而言,我的现在“足够好”,并指出我在问题中的原始示例可能只需要极小的变化。前任:
@Stéphane Chazelas的答案和我的问题下的评论(包括 ripgrep 的制造者本人的评论!)都很有用,并帮助我弄清楚了以下内容,我认为这是最简单和最好的答案,因为它是最简单的:
from 的输出路径字符串
rg
不是以 null 结尾的字符串,因此请从命令中删除-0
xargs
(或者相反,将其添加到rg
命令中)。而已!这现在有效:-0
或者,您可以通过将或添加--null
到命令来强制路径字符串以空值结尾rg
,所以这也可以:现在,通过扩展,我们可以
tree
像这样传递所有路径:最终答案:
而已!我只需要在两个和所有调用中添加或减去
-0
或添加或减去,以使它们保持一致并在解析多个路径时期望相同的轮廓符。--null
rg
xargs
但是,添加
-0
or--null
更好,因为它允许路径中包含空格或其他空格,并且添加--
也很好,因为它允许路径以破折号 (-
) 开头。所以,这就是我在上面所做的。不过,请再次查看其他答案。它还排序、删除重复项和处理其他复杂问题。
关键词:如何正确使用xargs;使用 xargs 解析 grep 或 ripgrep rg 输出路径