2017-03-03 92 views
2

我的動機是我正在使用多個git存儲庫,並且我想在所有這些存儲庫上運行git status以查看究竟是什麼。我怎樣才能在我的pushd棧上循環?

正如我經常存儲庫之間切換,我有他們在一個pushd棧,通過dirs -v示出爲:

0 /d/dev/helperscripts 
1 /d/dev/mainsite 
2 /d/dev/satellitesite 
3 /d/dev/apithing 

我試圖使用xargs如下遍歷它們:

dirs | xargs -n 1 -I % bash -c 'cd -- "%" && git status ' 

但是,這給出以下錯誤:

bash: line 0: cd: /d/dev/helperscripts /d/dev/mainsite /d/dev/satellitesite /d/dev/apithing: No such file or directory

我覺得這令人驚訝,因爲下面的結果是預期的目錄的線break'd列表:

dirs | xargs -n 1 echo 

回答

1

迪爾斯命令打印用空格隔開棧上目錄的列表,但在使用xargs-I選項時,xargs預計輸入將被換行符分隔。使用-p選項目錄可以將堆棧每行返回一個目錄,這會給出xargs它想要的內容。

此外,Bash通常會將您的主目錄替換爲目錄中的~列表中的。這可能會導致您的命令失敗,因爲替換會將目錄放在引號中,並且~在引用時會失去其特殊含義。使用-l選項至目錄強制它始終返回完整的未簡化路徑。

dirs -p -l | xargs -n 1 -I % bash -c 'cd -- "%" && git status ' 

編輯:

我原來的解決方案的目的是要回答爲什麼xargs的嗆得上的迪爾斯輸出的主要問題。然而,正如Ole Tange在評論中正確地指出的那樣,它仍然不能正確處理其中包含空格或其他shell元字符的目錄名稱。這正是xargs -0打算解決的問題,但Bash不提供使用NULL作爲分隔符顯示目錄堆棧的簡便方法。

一個替代方案將改爲地遍歷$DIRSTACK陣列,其中包含相同列表顯示目錄將產生:

function dirs_git_status 
{ 
    for d in "${DIRSTACK[@]}" 
    do 
     git --git-dir="${d}/.git" --work-tree="$d" status 
    done 
} 

"${DIRSTACK[@]}"符號確保每個完整數組元素中$d複製只要$d用於循環內的雙引號內部,元字符應該被保留並按原樣傳遞給git而不是由Bash評估。

+0

無法用:慶典:0行:CD:〜/ tmp目錄/ IW:沒有這樣的文件或目錄 –

+1

它失敗的命令指定'「% 「(我從你的例子中逐字抄錄)。這擴展爲'「〜/ tmp/iw」',並且'〜'在引號內使用時會失去其特殊含義。解決方案是'dirs -l'。我相應地更新了我的答案。 –

+0

在瘋狂的dirs上使用失敗:bash:line 0:cd:/ home/tange/tmp/<#&|()!!:沒有這樣的文件或目錄 –

0

如果使用GNU並行,這也將工作:

mkdir ~/tmp 
cd ~/tmp 
# Make some crazy dirs 
mkdir -- -a'" "'"' '"b '<#&|()[email protected]!!' 
pushd -- -a*b 
pushd .. 
pushd '<#&|()[email protected]!!' 
pushd ../.. 

dirs -p | parallel cd -- '{= s/^~/$ENV{HOME}/ =}' '&&' pwd 
dirs -p -l | parallel cd -- {} '&&' pwd