如何在zsh中迭代命令输出的所有行?

时间:2011-10-13 06:52:24

标签: iteration zsh lines

如何使用zsh迭代命令输出的所有行,而不设置IFS?

原因是我想对命令输出的每个文件运行一个命令,其中一些文件包含空格。

例如,给定已删除的文件:

foo/bar baz/gamma

即单个目录'foo',包含子目录'bar baz',包含文件'gamma'。

然后跑步:

git ls-files --deleted | xargs ls

将该文件中的报告作为两个文件处理:'foo / bar'和'/ baz / gamma'。

我需要它来处理一个文件:'foo / bar baz / gamma'。

2 个答案:

答案 0 :(得分:7)

如果要为所有行运行一次命令:

ls "${(@f)$(git ls-files --deleted)}"

f parameter expansion flag表示将命令的输出拆分为换行符。有一个更通用的格式(@s:||:)可以分割为||之类的任意字符串。 @标志表示保留空记录。有点令人困惑的是,整个扩展需要在双引号内,以避免IFS分割command substitution的输出,但它会为每条记录生成单独的单词。

如果你想依次为每一行运行命令,便携式习语并不是特别复杂:

git ls-filed --deleted | while IFS= read -r line; do ls $line; done

如果要在命令行长度限制允许的情况下运行命令几次,请使用zargs

autoload -U zargs
zargs -- "${(@f)$(git ls-files --deleted)}" -- ls

答案 1 :(得分:4)

使用tr-0的{​​{1}}选项,假设这些行不包含xargs(NUL),这是一个公平的假设,因为NUL是其中一个字符无法出现在文件名中:

\000

这会将行git ls-files --deleted | tr '\n' '\000' | xargs -0 ls 转换为foo/bar baz/gamma\n foo/bar baz/gamma\000知道如何处理