【问题标题】:How do I iterate over all the lines output by a command in zsh?如何遍历 zsh 中命令输出的所有行?
【发布时间】:2011-10-13 06:52:23
【问题描述】:

如何在不设置 IFS 的情况下使用 zsh 遍历命令输出的所有行?

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

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

foo/bar baz/gamma

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

然后运行:

git ls-files --deleted | xargs ls

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

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

【问题讨论】:

  • 你的系统有xargs命令吗?
  • @lunixboches:是的,确实如此 - 但是,它仍然无法正确处理这些行。
  • git ls-files -z | xargs -0 ls 将使用空 (\0) 分隔符而不是空格
  • @lunixbochs:也谢谢你。 :)

标签: iteration zsh lines


【解决方案1】:

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

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

fparameter expansion flag 表示将命令的输出拆分为换行符。有一种更通用的形式 (@s:||:) 可以在任意字符串处拆分,例如 ||@ 标志表示保留空记录。有点令人困惑的是,整个扩展需要在双引号内,以避免IFScommand 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

【讨论】:

  • 谢谢 - 这里有很多有用的信息,但我认为 xargs 仍然更有效,因为它会为每组文件运行一个命令。 (如果我有很多文件不适合 args 列表怎么办?)
  • @Arafangion zargs 类似于 xargs(在符合命令行长度限制的情况下运行尽可能少的实例),只有一个合理的界面。
【解决方案2】:

使用trxargs-0 选项,假设这些行不包含\000 (NUL),这是一个合理的假设,因为NUL 是不能包含的字符之一出现在文件名中:

git ls-files --deleted | tr '\n' '\000' | xargs -0 ls

这会将这条线:foo/bar baz/gamma\n 变成 foo/bar baz/gamma\000xargs -0 知道如何处理

【讨论】:

  • 再好不过了,谢谢! (它也适用于 bash!)
猜你喜欢
  • 1970-01-01
  • 2021-01-02
  • 2013-12-26
  • 2012-10-28
  • 2010-10-17
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
相关资源
最近更新 更多