2011-10-13 75 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