如何将人类可读的路径列表重定向到另一个命令?

如何将人类可读的路径列表重定向到另一个命令?

当使用命令的输出时,例如locate以“人类可读形式”生成路径列表(即\前面没有空格)的命令的输出,如何将它们的输出重定向到另一个命令?

的输出$ locate [something]会生成其中包含空格的路径,这将禁止其他程序使用包含空格的路径。例如,如果我要

$ du -h `locate *.doc`

这将对包含空格的所有文件和目录产生错误。 (将刻度线包裹在空格中不起作用)

答案1

您使用的具体原因是什么locate?这似乎符合您的要求:

find . -type f -name '*doc' -exec du -h "{}" \;

也就是说,如果你真的locate如果确实想要使用像or 这样的工具find并将其输入作为参数传递给另一个程序,您可以利用NUL某些工具提供的分隔输出和输入。 locate并且find两者都有一个选项(locate's-0find's -print0),这将允许您获得更加编程友好的输出,其xargs设计用于读取它是 -0争论:

find . -type f -name '*doc' -print0 | xargs -0 du -h

locate -0 '*doc' | xargs -0 du -h

答案2

如果您想要/需要将同一行传递给多个命令,则可以使用以下方法:

#!/usr/bin/env bash

T="${IFS}" # Save off the Internal Field Separator

IFS=$'\n' # Set it to newline.

while read file_line
do
        echo "--"
        echo "${file_line}"
        echo "--"
done <<< $(locate $1) 
IFS="${T}  # Set it back to the original IFS. 

包裹起来是个好主意任何“”中可能有空格的变量。

答案3

不加引号的命令替换($(...)`...`古老的形式)会在类似 Bourne 的 shell 中调用 split+glob(仅在 zsh 中拆分)。

默认情况下,分割是针对$IFS包含空格、制表符和换行符(以及 zsh 中的 NUL)的特殊参数的字符完成的,这解释了为什么您的命令不适用于包含空格字符的文件名。

你可以这样做:

(IFS='
' # split on newline only
set -o noglob # disable glob
du -hc -- $(locate '*.doc'))

但如果文件名包含换行符,这仍然会失败。的输出locate根本无法进行后处理。

大多数locate实现都有一个-0选项来输出文件路径NUL- 分隔。 NUL 是唯一不能出现在文件路径中的字节值,这意味着输出是可后处理的。您只需要按 NUL 进行拆分即可。

zsh

IFS=$'\0'
du -hc -- $(locate -0 '*.doc')

或者,更好的是,使用显式 split-on-NUL 运算符:

du -hc -- ${(0)"$(locate -0 '*.doc')"}

bash4.4+ 中,可能是:

readarray -td '' files < <(locate -0 '*.doc')
du -hc -- "${files[@]}"

这仍然留下两个问题:

  1. 如果locate找不到任何文件,du -hc --将不带参数运行,这意味着它将为您提供当前工作目录的磁盘使用情况。
  2. 另一方面,如果locate找到许多文件,您可能最终会达到系统调用的限制execve()并得到一个arg 列表太长错误。

通过执行以下操作可以避免这两个问题:

locate -0 '*.doc' | xargs -r0 du -hc --

-r并且-0是来自 GNU 实现的非标准扩展,xargs就像-h是来自 GNU 实现的非标准扩展du)。

然而,这引入了一个新问题:xargs将运行du多次来解决execve()限制,但这意味着您将得到几total行,并且多次硬链接的文件的磁盘使用情况可能最终会被计算多次。

感谢-r,如果找不到任何文件,则du不会运行,但这也意味着您不会得到一行。locate0 total

使用最新版本的 GNU du,可以通过以下方式解决这些问题:

locate -0 '*.doc' | du --files0-from=- -hc

这次,文件列表是通过管道而不是参数传递的,因此参数的大小没有限制。这也意味着不需要分配大量内存来存储该列表,并且du一旦locate开始输出它就可以开始处理它。

相关内容