Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何在pushd堆栈上循环?_Bash_Xargs - Fatal编程技术网

Bash 如何在pushd堆栈上循环?

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存储库,我想在所有这些存储库上运行
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--\“\\\”