递归列出Bash中给定目录中的文件

时间:2016-08-14 19:41:20

标签: linux bash shell

我知道可以使用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)。为什么我收到此错误?我在代码中遗漏了什么?

感谢。

3 个答案:

答案 0 :(得分:8)

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

继续前进,我建议您引用值(例如for x in "$1/"*lsRec "$x"lsRec "$arg")以避免路径包含空格字符时出现问题。当您在扫描的目录层次结构下创建名称中包含空格的目录时,您将到达目的地。

答案 1 :(得分:4)

这里的问题是"对于$ 1 *和#34;找到1美元,如果这是有道理的?所以它变成了无限循环。 有两种解决方案:

  • 检查x == $ 1
  • 将for循环更改为"对于$ 1 / *"
  • 中的x

因为$ 1被传递给函数的参数替换了吗?所以,如果它发送"你好"然后它变为"对于hello *"中的x。 现在,这是一个全球模式,将选择"你好"因此是一个无限循环。

第二种解决方案有效,因为"你好"成为"你好/ *"而不是"你好*"。

此代码适用于我:

#!/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";

希望它有所帮助!

答案 2 :(得分:2)

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

您应该将代码更改为:

#!/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;