2011-10-13 76 views
5

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

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

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

foo/bar baz/gamma 

即,单个目录“富”,含有子目录“栏巴兹”,包含文件“γ”。

然后运行:“富/酒吧”和“/巴兹/伽玛”:

git ls-files --deleted | xargs ls 

将在两个文件正在处理该文件报告。

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

+0

你的系统是否有xargs命令? – lunixbochs

+0

@lunixboches:是的,它确实 - 但是,它仍然无法正确处理这些行。 – Arafangion

+2

'git ls-files -z | xargs -0 ls'将使用null(\ 0)分隔符而不是空格 – lunixbochs

回答

4

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

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

这原来行:foo/bar baz/gamma\nfoo/bar baz/gamma\000xargs -0知道如何处理

+0

不能比这更好,谢谢! (并且它也在bash中工作!) – Arafangion

7

如果你想一次全部行运行命令:

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

fparameter 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 
+0

感谢您的信息 - 这里有很多有用的信息,但我认为xargs仍然更高效,因为它将为每组文件运行一个命令。 (如果我有那么多文件不适合在参数列表中,该怎么办?) – Arafangion

+0

@Arafangion'zargs'就像'xargs'(尽量少装入命令行长度限制内的实例),只有一个界面合理。 – Gilles

+0

更好,谢谢。 :)会检查出来。 – Arafangion