【问题标题】:Bash, Same variable being used in recursionBash,递归中使用相同的变量
【发布时间】:2016-04-13 10:58:32
【问题描述】:

我正在为 Uni 解决的一个问题是遍历一个目录并计算所有文件和目录以及子目录中的文件和目录。我无法使用命令 find、locate、du 或任何递归命令,例如 ls -R。为了解决这个问题,我正在创建自己的递归命令。我遇到了在每个递归中使用相同数组的问题,现在使用类似 java 的东西,递归会为递归中的每个变量分配不同的 id。但是这里使用了相同的变量。我可以从我的输出中看出它是从超级目录而不是正在使用的当前目录打印目录的位置。使用的层次结构是here,我得到的输出是here

tgtdir=$1
visfiles=0
hidfiles=0
visdir=0
hiddir=0
function searchDirectory {
    curdir=$1

    echo "curdir = $curdir" 
    # Rather than change directory ensure that each recursive call uses the $curdir/NameOfWantedDirectory
    noDir=$(ls -l -A $curdir| grep ^d | wc -l) # Work out the number of directories in the current directory
    echo "noDir = $noDir"

    shopt -s nullglob # Enable nullglob to prevent a null term being added to the array

    y=0 # Declares a variable to act as a index value
    for i in $( ls -d ${curdir}*/ ${curdir}.*/ ); do # loops through all directories both visible and hidden
        if [[ "${i:(-3)}" = "../" ]]; then
            echo "Found ../"
            continue;
        elif [[ "${i:(-2)}" = "./" ]]; then
            echo "Found ./"
            continue;
        else # When position i is ./ or ../ the loop advances otherwise the value is added to directories and y is incremented before the loop advances
            echo "Adding $i to directories"
            directories[y]="$i"
            let "y++"
        fi
    done # Adds all directories except ./ and ../ to the array directories
    shopt -u nullglob #Turn off nullglob to ensure it doesn't later interfere
    echo "${directories[@]}"
    if [[ "${noDir}" -gt "0" ]]; then
        for i in "${directories[@]}"; do
            searchDirectory $i
        done # Loops through subdirectories to reach the bottom of the hierarchy using recursion
    fi

    visfiles=$(ls -l $tgtdir | grep -v ^total | grep -v ^d | wc -l)
    # Calls the ls -l command which puts each file on a new line, then removes the line which states the total and any lines starting with a 'd' which would be a directory with grep -v,
    #finally counts all lines using wc -l
    hiddenfiles=$(expr $(ls -l -a $tgtdir | grep -v ^total | grep -v ^d | wc -l) - $visfiles) 
    # Finds the total number of files including hidden and puts them on a line each (using -l and -a (all)) removes the line stating the total as well as any directoriesand then counts them. 
    #Then stores the number of hidden files by expressing the complete number of files minus the visible files.
    visdir=$(ls -l $tgtdir | grep ^d | wc -l)
    # Counts visible directories by using ls -l then filtering it with grep to find all lines starting with a d indicating a directory. Then counts the lines with wc -l.
    hiddir=$(expr $(ls -l -a $tgtdir | grep ^d | wc -l) - $visdir)
    # Finds hidden directories by expressing total number of directories including hidden - total number of visible directories
    #At minimum this will be 2 as it includes the directories . and ..
    echo "Increased Values"
}
searchDirectory $tgtdir
echo "Total Files: $visfiles (+$hiddenfiles hidden)"
echo "Directories Found: $visdir (+$hiddir hidden)"
echo "Total files and directories: $total"
exit 0

【问题讨论】:

  • 如果您使用 bash,我认为 local 关键字是您的朋友。
  • 声明你的本地人!
  • 另外,说真的,您不能构建一个 3 行复制器吗?这远远,远远比问题要求的更多代码;见stackoverflow.com/help/mcve
  • 同意,很高兴看到一些代码,并且您显然已经尝试解决您的问题,但是如果我们不被其他所有事情分散注意力,我们会更容易为您提供帮助你的代码。
  • 顺便说一句,您的原始问题中还有其他错误,shellcheck.net 会自动找到。

标签: arrays linux bash recursion directory


【解决方案1】:

根据this,您应该使用localdirectories 声明为局部变量。如果省略,变量将是全局的。试试看吧。

【讨论】:

  • 不仅仅是directories——还有curdirnoDiri和其他所有变量。
  • 顺便说一句,我强烈建议您避免将 ABS 用作参考;虽然它确实有很多 Google 果汁,但它经常在其示例中使用不良做法;我们这些花时间在 freenode 的 #bash 频道上的人,经常背负着帮助人们忘记他们在那里学到的不良做法的重担。
  • 干杯,这解决了问题
  • @CharlesDuffy 哇,很高兴知道这一点。我会记住这一点,谢谢。
【解决方案2】:

考虑一个更简单的复制器:

foo() {
  var=$1
  (( var > 10 )) && return
  foo "$(( $var * 2 ))"
  echo "Passed $var"
}

( foo 1 )

因为 shell 中的所有变量都是全局的,除非另有明确声明,只需使用 var=$1,这将发出:

Passed 16
Passed 16
Passed 16
Passed 16

使用local vardeclare var,这将正确发出:

Passed 8
Passed 4
Passed 2
Passed 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 2011-11-20
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多