如何在我的pushd堆栈上循环?

时间:2017-03-03 18:11:23

标签: bash xargs

我的动机是我正在使用多个git存储库,并且我希望在所有这些存储库上运行git status以查看它是什么。

当我经常在存储库之间切换时,我将它们放在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

我发现这令人惊讶,因为下面的结果是按预期的目录的换行符列表:

dirs | xargs -n 1 echo

2 个答案:

答案 0 :(得分:1)

dirs 命令打印堆栈上以空格分隔的目录列表,但在使用 xargs -I选项时, xargs 期望输入由换行符分隔。使用 dirs -p选项返回每行一个目录的堆栈,这将为 xargs 提供所需的内容。

此外,Bash通常会使用 dirs 列表中的~替换您的主目录。这可能会导致命令失败,因为替换将目录括在引号中,~在引用时失去其特殊含义。使用{strong> dirs 的-l选项强制它始终返回完整的未缩写路径。

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

编辑:

我原来的解决方案旨在回答为什么 xargs dirs 的输出上窒息的主要问题。但是,正如Ole Tange在评论中正确指出的那样,它仍然不能正确处理带有空格或其他shell元字符的目录名。这正是xargs -0旨在解决的问题,但是Bash没有提供使用NULL作为分隔符来显示目录堆栈的便捷方法。

另一种选择是循环遍历$DIRSTACK数组,该数组包含 dirs 会产生的相同列表:

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

"${DIRSTACK[@]}"表示法确保将每个完整的数组元素复制到$d,并且只要在循环内的双引号内使用$d,就应保留元字符并且按原样传递给 git ,而不是由Bash评估。

答案 1 :(得分:0)

如果你使用GNU Parallel,它也可以工作:

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

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