如何使用zsh迭代命令输出的所有行,而不设置IFS?
原因是我想对命令输出的每个文件运行一个命令,其中一些文件包含空格。
例如,给定已删除的文件:
foo/bar baz/gamma
即单个目录'foo',包含子目录'bar baz',包含文件'gamma'。
然后跑步:
git ls-files --deleted | xargs ls
将该文件中的报告作为两个文件处理:'foo / bar'和'/ baz / gamma'。
我需要它来处理一个文件:'foo / bar baz / gamma'。
答案 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
知道如何处理