Bash 如何在pushd堆栈上循环?
我的动机是使用多个git存储库,我想在所有这些存储库上运行Bash 如何在pushd堆栈上循环?,bash,xargs,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
,看看是什么
由于我经常在存储库之间切换,我将它们放在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/helperscript/d/dev/mainsite/d/dev/satellitestite/d/dev/apithing:没有这样的文件或目录
我发现这一点令人惊讶,因为下面是一个按预期换行的目录列表:
dirs | xargs -n 1 echo
dirs命令打印堆栈上以空格分隔的目录列表,但是当使用
-I
选项时,xargs希望输入以换行分隔。使用-p
选项dirs返回每行一个目录的堆栈,这将提供xargs所需的内容
此外,Bash通常会在dirs列表中用~
替换您的主目录。这可能会导致您的命令失败,因为替换将目录括在引号中,~
在引号中失去其特殊意义。使用-l
选项dirs强制它始终返回完整的未修改路径
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进行计算。如果使用GNU并行,这也将起作用:
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
mkdir~/tmp
cd~/tmp
#做一些疯狂的DIR
mkdir---a'''''''''b'失败:bash:line 0:cd:~/tmp/iw:没有这样的文件或目录它失败命令指定“%”
(我从您的示例中逐字复制了它)。这扩展到“~/tmp/iw”
,~
在引号中使用时失去了其特殊意义。解决方法是dirs-l
。我已经相应地更新了我的答案。当在疯狂的目录上使用时失败:bash:line 0:cd:/home/tange/tmp/当使用xargs时,请始终在以-,包含多个空格“和”开头的输入上测试您的解决方案。例如mkdir--\“\\\”