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

时间:2018-11-27 16:40:08

标签: linux bash shell while-loop scope

在我的脚本中,我想计算在不同目录中有多少目录和文件。在“任务”中,我有很多名为“ 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循环结束后,我丢失了这三个变量的值。我知道发生这种情况是因为while循环是子外壳程序,但是我不知道如何以某种方式“存储”父外壳程序的变量值。当我知道这是最后一个“ aPathOfRepoDir”时,我考虑过在while循环中打印这些消息,但这有点“便宜”,而且效率不高。还有另一种方法吗?

预先感谢

2 个答案:

答案 0 :(得分:2)

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

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"/ )

答案 1 :(得分:0)

如何?

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还将发出文件类型以简化分类
  • “分类”功能将遍历查找输出以计算各种类别。
  • not parsing ls
  • 该功能有助于在单个子外壳中定位所有变量