代码之家  ›  专栏  ›  技术社区  ›  Vicky Dev

无法在存储在变量中的路径中的目录中循环

  •  0
  • Vicky Dev  · 技术社区  · 5 年前

    我就是不明白,为什么我不能做我刚才提到的问题?

    为了更清楚地说明,我尝试在某个路径中遍历所有目录,该路径存储在我选择的任何随机变量中。请看下面的脚本,让我知道为什么执行没有通过 for

    gpll_allrepos3() {
        export SIMPROJS="/c/Projects/mainproject"
        currPath=$(pwd)
        for repoFolder in $SIMPROJS; do
            echo "RepoFolder: $repoFolder"
            if [[ -d "$SIMPROJS/$repoFolder/.git" && ! -L "$SIMPROJS/$repoFolder/.git" ]]; then
                echo "$SIMPROJS/$repoFolder"
                cd "$SIMPROJS/$repoFolder" && echo "Now inside $SIMPROJS/$repoFolder"
                curr_branch=$(git rev-parse --abbrev-ref HEAD)
                ## git pull && git pull origin
                ## if [[ "$curr_branch" != "master" ]]; then
                    ### Merging master branch as the current branch is feature branch
                    git checkout master
                    git pull && git pull origin
                    git checkout $curr_branch
                    git merge master
                ## fi
            fi
        done
        cd $currPath
    }
    gpll_allrepos3
    

    我不是一个很好的Bash脚本,所以任何建议都很感激,但请注意,我需要能够从任何地方运行这个脚本,我选择。

    3 回复  |  直到 5 年前
        1
  •  1
  •   Gordon Davisson    5 年前

    for 它不遍历目录的内容,而是遍历一系列“单词”(基本上是字符串)。因此,本声明:

    for var in alice bob "jimmy joe" /c/Projects/mainproject; do
    

    …将运行其内容四次,第一次是 var /c/Projects/mainproject/* 目录/c/Projects/mainproject/(包括路径前缀)中的文件列表。因此,您可以使用:

    for repoFolder in "$SIMPROJS"/*; do
    

    注意变量引用周围的双引号?这样做几乎总是一个好主意,否则shell将根据空格(或任何在 IFS * 必须是 双引号,这样它将扩展到一个文件列表,而不仅仅被视为一个文本文件名。

    另外,请注意,这将遍历/c/Projects/mainproject中的文件和子目录。如果只需要子目录,请使用以下命令:

    for repoFolder in "$SIMPROJS"/*/; do
    

    添加的尾部斜杠将其限制为仅匹配目录(因为目录路径末尾的斜杠有意义,但普通文件路径末尾的斜杠没有意义)。但是请注意,后面的斜杠也会包含在结果路径中。

    "$SIMPROJS/$repoFolder" repoFolder 变量已经包含路径前缀(因为它包含在扩展的通配符字符串中),所以再次添加它会导致麻烦。只是使用 "$repoFolder" .

    另外,当你使用 cd

    cd "$SIMPROJS/$repoFolder" && echo "Now inside $SIMPROJS/$repoFolder"
    

    …如果失败(这是因为路径加倍问题),它将不会打印“Now inside…”消息,而是继续处理其他所有内容。您应该使用以下内容:

    cd "$repoFolder" || {
        echo "Couldn't cd into $repoFolder, cancelling..." >&2
        return 1
    }
    

    …这将退出功能,而不是盲目地继续在错误的地方。

    顺便提一下 shellcheck.net 善于发现这些常见问题;我建议您通过它运行脚本,至少在您更熟悉shell脚本之前是这样。

        2
  •  1
  •   miken32    5 年前

    要循环浏览目录中的文件,需要提供一个可以 expanded to a filename glob .

    一旦你有了它,你的循环变量将包含整个路径,所以不需要前缀原始目录名。

    你也可以用 pushd popd $currPath 变量。

    #!/bin/bash
    simprojs="/c/Projects/mainproject"
    for repoFolder in "$simprojs"/*; do
        if [[ -d "$repoFolder/.git" && ! -L "$repoFolder/.git" ]]; then
            pushd "$repoFolder" && echo "Now inside $repoFolder"
            curr_branch=$(git rev-parse --abbrev-ref HEAD)
            git checkout master
            git pull && git pull origin
            git checkout "$curr_branch"
            git merge master
        fi
    done
    popd
    
        3
  •  1
  •   masseyb    5 年前

    一个脚本对于这个问题似乎杀伤力过大,可以使用 find : find $SOMEPATH -type d -name .git -execdir git checkout master \; -execdir git pull && git pull origin \; -execdir ... \; .

    目录( -type d )名为“.git”( -name .git )在 $SOMEPATH . 对于每个.git目录运行 command -execdir command \; -execdir command \; -execdir ... \; ).

    你不需要这么做 cd 对于.git目录,您不需要维护一堆目录(例如。 pushd popd 从不遵循符号链接(参考op ! -L