【问题标题】:Recursively list files from a given directory in Bash递归列出 Bash 中给定目录中的文件
【发布时间】:2016-08-14 19:41:19
【问题描述】:

我知道可以使用ls -R path 来完成。但是我正在尝试学习shell语言的语法和控制结构,所以我正在尝试编写自己的代码:

#!/bin/sh

arg=$1;

lsRec() {
    for x in $1*; do
        if [ -d "$x" ]; then
            lsRec $x;
        else
            echo "$x";
        fi
    done
}

lsRec $arg;

当我调用命令./ej2.sh ~/Documents/ 时,终端会抛出:segmentation fault (core dumped)。为什么会出现此错误?,我的代码中是否缺少某些内容?

谢谢。

【问题讨论】:

  • 顺便说一句:您已将问题标记为 bash,但您的 shebang 行以 sh 为目标,并且您正在使用(仅)sh 兼容语法。
  • 另一边:如果您将 多个 语句放在同一行上,您只需要 ; 来终止语句(但请注意 dothen 如果放置在同一行上,则需要前面的;)。

标签: linux bash shell


【解决方案1】:

您的算法正在进入无限循环,因为lsRec 函数隐含地期望其参数以“/”结尾。第一级有效,因为您传递以“/”结尾的路径作为输入,但第二级没有,因为您进行递归调用的路径不以“/”结尾。您可以做的是在进行递归调用时添加斜杠,使其看起来像lsRec $x/,或者(更好)在循环参数中添加斜杠,如for x in $1/*; do (因为系统通常会忽略多个相邻的路径分隔符)。

接下来,我建议您引用这些值(例如 for x in "$1/"*lsRec "$x"lsRec "$arg")以避免路径包含空白字符时出现问题。当您在正在扫描的目录层次结构下创建一个名称中带有空格的目录时,您就会到达那里。

【讨论】:

    【解决方案2】:

    这里的问题是“for x in $1*”找到 $1,如果这有意义吗?所以它变成了一个无限循环。 有两种解决方案:

    • 检查 x == $1
    • 将 for 循环更改为“for x in $1/*”

    因为 $1 被传递给函数的参数所取代,对吧?因此,如果它发送“hello”,那么它就变成“for x in hello*”。 现在,这是一个 globbing 模式,将选择“hello”,因此是一个无限循环。

    第二种解决方案有效,因为“hello”变成了“hello/*”而不是“hello*”。

    这段代码对我来说很好用:

    #!/bin/sh
    
    arg=$1;
    
    lsRec() {
        for x in "$1"/*; do
            echo "$x"
            if [ -d "$x" ]; then
                echo "This is a directory:"
                lsRec "$x";
            else
                echo "This is not a directory:"
                echo "$x";
           fi
        done
    }
    
    lsRec "$arg";
    

    希望对你有帮助!

    【讨论】:

    • 斜线还不见了? :)
    • @mike.dld 啊,是的。现在修好了。谢谢m8!
    • @mklement0 现在好点了吗?
    【解决方案3】:

    我认为你制造了一个叉形炸弹。您的代码创建了一个无限递归。

    您应该将代码更改为:

    #!/bin/sh
       arg=$1;
    
       lsRec() {
          for x in $1/*; do
            if [ -d "$x" ]; then
                echo "$x"  ## here you print the line
                lsRec $x; ## here you pass the contents and NOT the line itself
                            ## your programm was passing dirs without processing
                            ## over and over
            else
                echo "$x";
            fi
        done
    }
    
    lsRec $arg;
    

    【讨论】:

      猜你喜欢
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 2016-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多