如何对 find 命令的每个结果运行 wc ?

Sae*_*ati 5 bash find wc

我想查看使用该命令找到的每个文件中存在多少行find

我知道我可以用来wc -l查找单个文件的行数。但是,当从以下输出进行管道传输时,这不起作用find

find -type f -name package.json | wc -l
Run Code Online (Sandbox Code Playgroud)

这将返回找到的文件的计数。我想返回每个找到的文件的行数。

Sté*_*las 10

wcw获取其字节/字符/命令/行计数c的文件列表参数的

当不带参数调用时,它会在其标准输入中报告这些字节/字符/单词/行。因此,如果您通过管道传输findwc -l,您将在输出中获得换行符的数量find,因此这将是找到的文件的数量加上其路径中的换行符的数量。

GNU 实现wc还可以使用该选项从文件中获取以 NUL 分隔的文件列表--files0-from,它将其视为-意义 stdin (而不是名为 的文件-),因此您可以执行以下操作:

find . -name package.json -type f -print0 |
  wc -l --files0-from=-
Run Code Online (Sandbox Code Playgroud)

对于任何标准findwc实现,您都可以将find文件路径列表作为参数wc传递给:

find . -name package.json -type f -exec wc -l {} +
Run Code Online (Sandbox Code Playgroud)

但是,如果有大量匹配文件,则最终可能会运行wc多次,从而导致多次出现total

wctotal当给定至少 2 个要处理的文件时打印该行,因此要跳过该total行,您可以执行以下操作:

find . -name package.json -type f -exec wc -l {} ';'
Run Code Online (Sandbox Code Playgroud)

尽管这会非常低效,因为分叉进程并为每个文件执行命令非常昂贵。

如果这是您真正感兴趣的总数,那么您会这样做:

find . -name package.json -type f -exec cat {} + | wc -l
Run Code Online (Sandbox Code Playgroud)

我们将cat这些文件内容的连接提供给wc提供给.

使用zsh和 any wc,你可以这样做:

wc -l -- **/package.json(D.)
Run Code Online (Sandbox Code Playgroud)

D对于Dotglob 来说,也可以像这样做一样获取隐藏文件,find并且.只包含常规文件,相当于-type f)。

这样做的好处是可以为您提供一个排序列表并避免./前缀。

这次,如果没有或太多匹配文件,您将收到错误。

使用 GNU du,您可以通过将 NUL 分隔的 glob 扩展传递给wc -l --files0-from=-with 来避免这些问题:

print -rNC1 -- **/package.json(ND.) | wc -l --files0-from=-
Run Code Online (Sandbox Code Playgroud)

另请注意,在 json 格式中,换行符(其中wc -l重要)并不重要,因此我不确定这是否是您获得的有用指标。

例如,您可以返回这些文件中某些数组中的元素数量,而不是:

find . -name package.json -type f -exec \
  jq -r '[.devDependencies|length,input_filename]|@csv' {} +
Run Code Online (Sandbox Code Playgroud)

(假设文件路径是 UTF-8 编码文本,此处给出 CSV 格式的结果)。