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
Linux 在bash中退出while循环时丢失变量值_Linux_Bash_Shell_While Loop_Scope - Fatal编程技术网

Linux 在bash中退出while循环时丢失变量值

Linux 在bash中退出while循环时丢失变量值,linux,bash,shell,while-loop,scope,Linux,Bash,Shell,While Loop,Scope,在我的脚本中,我想计算在不同目录中有多少目录和文件。在“assignments”中,我有许多名为“repo1”、“repo2”等的目录。以下是我的代码: ls -1 assignments | while read -r repoDir do find assignments/"$repoDir" | grep -v .git | grep "$repoDir"/ | while read -r aPathOfRepoDir do BASENAME=`basena

在我的脚本中,我想计算在不同目录中有多少目录和文件。在“assignments”中,我有许多名为“repo1”、“repo2”等的目录。以下是我的代码:

ls -1 assignments | while read -r repoDir
do
    find assignments/"$repoDir" | grep -v .git | grep "$repoDir"/ | while read -r aPathOfRepoDir
    do
        BASENAME=`basename "$aPathOfRepoDir"`
        if [[ -d "$aPathOfRepoDir" ]]; then
            totalDirectories=$((totalDirectories+1))
        elif [[ -f "$aPathOfRepoDir" ]] && [[ "$BASENAME" == *".txt" ]]; then
            totalTextFiles=$((totalTextFiles+1))
        else
            totalOtherFiles=$((totalOtherFiles+1))
        fi
    done
    echo "total directories: $totalDirectories"
    echo "total text files: $totalTextFiles"
    echo "total other files: $totalOtherFiles"
    totalDirectories=0
    totalTextFiles=0
    totalOtherFiles=0;
done
当while循环完成时,我将丢失这3个变量的值。我知道这是因为while循环是一个子shell,但我不知道如何“存储”父shell的变量值。当我知道这是最后一个“aPathOfRepoDir”时,我考虑在while循环中打印这些消息,但这是一种“便宜”的方式,效率不高。还有别的办法吗


提前感谢

管道的右侧在子外壳中运行。子shell变量中的更改不会传播到父shell。使用流程替代:

while read -r aPathOfRepoDir
    do
        BASENAME=`basename "$aPathOfRepoDir"`
        if [[ -d "$aPathOfRepoDir" ]]; then
            totalDirectories=$((totalDirectories+1))
        elif [[ -f "$aPathOfRepoDir" ]] && [[ "$BASENAME" == *".txt" ]]; then
            totalTextFiles=$((totalTextFiles+1))
        else
            totalOtherFiles=$((totalOtherFiles+1))
        fi
    done < <(find assignments/"$repoDir" | grep -v .git | grep "$repoDir"/ )
读取时-r
做
BASENAME=`BASENAME“$aPathOfRepoDir”`
如果[-d“$APATHOFROPDIR”];然后
TotalDirectory=$((TotalDirectory+1))
elif[[-f“$aPathOfRepoDir”]]和&[“$BASENAME”==*”.txt”];然后
totalTextFiles=$((totalTextFiles+1))
其他的
totalOtherFiles=$((totalOtherFiles+1))
fi

完成子外壳中管路的右侧。子shell变量中的更改不会传播到父shell。使用流程替代:

while read -r aPathOfRepoDir
    do
        BASENAME=`basename "$aPathOfRepoDir"`
        if [[ -d "$aPathOfRepoDir" ]]; then
            totalDirectories=$((totalDirectories+1))
        elif [[ -f "$aPathOfRepoDir" ]] && [[ "$BASENAME" == *".txt" ]]; then
            totalTextFiles=$((totalTextFiles+1))
        else
            totalOtherFiles=$((totalOtherFiles+1))
        fi
    done < <(find assignments/"$repoDir" | grep -v .git | grep "$repoDir"/ )
读取时-r
做
BASENAME=`BASENAME“$aPathOfRepoDir”`
如果[-d“$APATHOFROPDIR”];然后
TotalDirectory=$((TotalDirectory+1))
elif[[-f“$aPathOfRepoDir”]]和&[“$BASENAME”==*”.txt”];然后
totalTextFiles=$((totalTextFiles+1))
其他的
totalOtherFiles=$((totalOtherFiles+1))
fi
完成<这个怎么样:

classify() {
    local -A types=([dir]=0 [txt]=0 [other]=0)
    local n=0
    while read -r type path; do 
        if [[ $type == d ]]; then
            (( types[dir] ++ ))
        elif [[ $type == f && $path == *.txt ]]; then
            (( types[txt] ++ ))
        else
            (( types[other] ++ ))
        fi
        ((n++))
    done
    if [[ $n -gt 0 ]]; then
        echo "$1"
        echo "total directories: ${types[dir]}"
        echo "total text files: ${types[txt]}"
        echo "total other files: ${types[other]}"
    fi
}

for repoDir in assignments/*; do 
    find "$repoDir" \
        \( ! -path "$repoDir" -a ! -path '*/.git' -a ! -path '*/.git/*' \) \
        -printf '%y %p\n' \
    | classify "$repoDir"
done
  • find
    可以排除您不想看到的文件
  • find还将发出文件类型以简化分类
  • “分类”功能将循环查找输出,以统计各种类别
  • 该函数有助于在单个子shell中本地化所有变量
    • 这个怎么样:

      classify() {
          local -A types=([dir]=0 [txt]=0 [other]=0)
          local n=0
          while read -r type path; do 
              if [[ $type == d ]]; then
                  (( types[dir] ++ ))
              elif [[ $type == f && $path == *.txt ]]; then
                  (( types[txt] ++ ))
              else
                  (( types[other] ++ ))
              fi
              ((n++))
          done
          if [[ $n -gt 0 ]]; then
              echo "$1"
              echo "total directories: ${types[dir]}"
              echo "total text files: ${types[txt]}"
              echo "total other files: ${types[other]}"
          fi
      }
      
      for repoDir in assignments/*; do 
          find "$repoDir" \
              \( ! -path "$repoDir" -a ! -path '*/.git' -a ! -path '*/.git/*' \) \
              -printf '%y %p\n' \
          | classify "$repoDir"
      done
      
      • find
        可以排除您不想看到的文件
      • find还将发出文件类型以简化分类
      • “分类”功能将循环查找输出,以统计各种类别
      • 该函数有助于在单个子shell中本地化所有变量

      这对于包含换行符但可以更正的文件名很容易受到攻击。对于包含换行符但可以更正的文件名很容易受到攻击。