2017-03-03 91 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