【问题标题】:Recursive bash function (directory iterator)递归 bash 函数(目录迭代器)
【发布时间】:2016-10-17 00:31:54
【问题描述】:

我知道我的以下任务可以使用更简单的“查找”注释来完成,但我正在尝试使用递归调用来实现解决方案。我正在查看特定目录并尝试获取所有子目录中任何文件名的最大长度。但是,我的递归只工作了一层,所以它基本上返回了某个目录或其子目录中最长的文件名。

#! /bin/bash

export maxlen=0

findmaxr()
{
        if [ $# -eq  0 ] ; then
        echo "Please pass arguments. Usage: findmax dir"
        exit -1
        fi

        if [ ! -d "$1" ];       then
        echo "No such directory exist."
        exit -2
        fi

        for file in $(/bin/ls $1)
                do
                if [ -d "$file" ] ; then
                        findmaxr $file   # Recursively call the method for subdirectories
                else
                        cur=${#file}
                        if [ $maxlen -lt $cur ] ; then
                                maxlen=$cur
                        fi
                fi
                done

        echo "The file with the longest name has [$maxlen] characters."



}

findmaxr `pwd`

【问题讨论】:

    标签: bash unix recursion


    【解决方案1】:

    这里有几个问题。最大的是在[ -d "$file" ]findmaxr $file 中,file 变量只包含文件名,而不是整个路径。所以,如果你在 /dir 中,并且 /dir/sub/sub2 存在,顶层将运行 findmaxr /dir (这很好),它将运行 findmaxr sub (它有效,但不是你真正想要的想要),然后运行findmaxr sub2(根本不起作用)。所以一种可能性是在这些行中使用"$1/$file",但还有另一个问题:parsing ls is a bad idea and will fail for some directory names。最好使用for path in "$1"/*,它没有解析问题(前提是你双引号引用所有变量引用,无论如何你都应该这样做)并且为你提供完整路径,所以你不要'不必在前面加上$1/。但是你必须在检查文件名长度之前去掉路径的前面,比如local file="$(basename "$path")"

    第二个问题是它在完成每个目录之后打印$maxlen,而不是在扫描整个树之后。要解决这个问题,只需将该命令从递归函数中移出到主序列中,在它运行 findmaxr 之后。

    还有另一个更微妙的问题:filecurpath,如果您遵循我的建议)不是局部变量,这意味着递归调用可以在 findmaxr 的调用实例中更改它们的值.您应该将它们声明为局部变量以避免混淆。哦,没有必要导出 maxlen ——它会自动在脚本中是全局的,并且与您正在运行的任何命令(export 将其传递给)都无关。

    【讨论】:

    • 谢谢。我在其他地方读到解析 ls 是有问题的,但找不到解释。您提供的信息非常有用!
    【解决方案2】:

    findmaxr 的每个实例都需要返回它找到的 maxlen(通过 echo),您需要在比较中包含该输出。

    还有一个问题:假设abc是目录,d.txt是一个文件,它们的排列是这样的:a/b/c/d.txt。从a 内部运行脚本。当filebif [ -d "$file" ] 为真,findmaxr b 被调用。它调用ls b,这又导致findmaxr c,这导致ls c...除了ls c失败,因为你还在a。您需要将cd 放入子目录中,或者包含整个路径,如下所示:$1/$file

    这是您修复了这些问题的脚本:

    #!/bin/bash
    
    findmaxr()
    {
        if [ $# -eq  0 ] ; then
        echo "Please pass arguments. Usage: findmax dir"
        exit -1
        fi
    
        if [ ! -d "$1" ];       then
        echo "No such directory exist."
        exit -2
        fi
    
        maxlen=0
        for file in $(/bin/ls "$1")
                do
                if [ -d "$1/$file" ] ; then
                        cur=`findmaxr "$1/$file"`   # Recursively call the method for subdirectories
                else
                        cur=${#file}
                fi
                if [ $maxlen -lt $cur ] ; then
                    maxlen=$cur
                fi
            done
            echo $maxlen
    }
    
    maxlen=$(findmaxr $(pwd))
    echo "The file with the longest name has [$maxlen] characters."
    

    【讨论】:

      猜你喜欢
      • 2012-11-06
      • 2013-12-01
      • 1970-01-01
      • 2019-04-03
      • 2016-03-01
      • 2021-12-31
      • 2020-10-09
      • 2013-01-13
      相关资源
      最近更新 更多