6

I know that it can be done using ls -R path. But I'm trying to learn the syntax and control structures of the shell language, so I'm trying to write my own code:

#!/bin/sh

arg=$1;

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

lsRec $arg;

When I call the command ./ej2.sh ~/Documents/, the terminal throws: segmentation fault (core dumped). Why I'm getting this error?, Am I missing something in my code?

Thanks.

2
  • 2
    As an aside: you've tagged the question bash, but your shebang line targets sh, and you're using (only) sh-compatible syntax.
    – mklement0
    Commented Aug 14, 2016 at 20:13
  • 2
    Another aside: You only need ; to terminate statements if you place multiple statements on the same line (but note that do and then do need a preceding ; if placed on the same line).
    – mklement0
    Commented Aug 14, 2016 at 20:36

3 Answers 3

8

Your algorithm is entering endless loop since lsRec function implicitly expects its argument to end in "/". First level works, as you pass path ending with "/" as input, but second level doesn't, as the path you're making recursive call with doesn't end in "/". What you could do is either add the slash when you make a recursive call, so it'll look like lsRec $x/, or (better yet) add the slash in the loop arguments as in for x in $1/*; do (as system generally ignores multiple adjacent path separators).

Moving forward, I'd advise you to quote the values (e.g. for x in "$1/"*, lsRec "$x", lsRec "$arg") to avoid issues when path contains whitespace characters. You'll get there when you create a directory with space in its name under directory hierarchy you're scanning.

0
5

The problem here is that "for x in $1*" finds $1, if that makes sense? So it becomes an infinite loop. There are two solutions:

  • Check if x == $1
  • Change the for loop to "for x in $1/*"

Because $1 is replaced by the argument passed to the function right? So if it sends "hello" then it becomes "for x in hello*". Now, that is a globbing pattern and will select "hello" and thus an infinite loop.

The second solution works because "hello" becomes "hello/*" instead of "hello*".

This code works fine for me:

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

Hope it helps!

3
  • 3
    The slash is still missing? :)
    – mike.dld
    Commented Aug 14, 2016 at 20:00
  • 1
    @mike.dld Ah yes. Fixed now. Thanks m8! Commented Aug 14, 2016 at 20:43
  • 1
    @mklement0 Better now? Commented Aug 14, 2016 at 20:50
2

I think you created a fork bomb. Your code creates an infinite recursion.

You should change the code to:

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.