1

I'm starting with this simple code, which goes through /home/ and determines whether an object is a file or a directory

#!/usr/bin/perl


# My Starting directory.  I could also read this from the command line
$start = "/home/";
$count = 0; # How many non-file objects found.  Line un-necessary

# Initialize the list
push (@dirs, $start);

# Iterate through the list (really a queue) 
# We could also do this with a shift, but this works
foreach $curr (@dirs)
    {
    # Get the directory listing for the current directory
    # Note that -F appends a character for the type of object it is
    # on the end (/) for directory.


    my @lines = split /\n/, `ls -F $curr`;

    # Iterate through the things we got from the ls
    foreach $line (@lines)
    {
        # The chomp is not necessary because the split strips out
        # the seperator characters.
        #chomp $line;

        # If it ends in a / it's a directory. add it to the end of
        # the list
        if ($line =~ m#/$#)
        {
            print "Directory of -> " . $curr.$line . "\n";
            push(@dirs, ($curr.$line));
        }
        else
        {
            print "File of ==> " . $curr.$line . "\n";
            $count++;
        }
    }
}

# Silly print statement
print "I found " . $count . " non-directory objects.\n";

And I tried modifying it to use ls -l since the rest of the program depends on the info from it, but that's where things go weird.

What I modified:

my @lines = `ls -l $curr`;

if ($line =~ m#-.........#)

elsif ($line =~ m#d.........#)

I don't mean to keep the regex that way, I was going to do it the right way once I got it to actually proceed correctly.

And I added a stupid debug, right after the foreach

print("$line \n");

What I should get is kind of like this:

File of ==> /home/paul/perl/spider*
Directory of -> /home/paul/perl/test/
I found 9 non-directory objects.

Instead, I get this:

total 8

drwxr-xr-x 28 paul paul 4096 2014-03-11 01:31 paul

Directory of -> /home/drwxr-xr-x 28 paul paul 4096 2014-03-11 01:31 paul

drwxr-xr-x  2 test test 4096 2014-03-10 02:12 test

Directory of -> /home/drwxr-xr-x  2 test test 4096 2014-03-10 02:12 test

ls: cannot access /home/drwxr-xr-x: No such file or directory
ls: cannot access 28: No such file or directory
ls: cannot access paul: No such file or directory
ls: cannot access paul: No such file or directory
ls: cannot access 4096: No such file or directory
ls: cannot access 2014-03-11: No such file or directory
ls: cannot access 01:31: No such file or directory
ls: cannot access paul: No such file or directory
ls: cannot access /home/drwxr-xr-x: No such file or directory
ls: cannot access 2: No such file or directory
ls: cannot access 4096: No such file or directory
ls: cannot access 2014-03-10: No such file or directory
ls: cannot access 02:12: No such file or directory
test:

total 0



test:

total 0



test:

total 0

I found 0 non-directory objects.

I'm at wit's end and don't understand why everything else I've tried has failed as well. Thanks in advance!

xG33Kx
  • 25
  • 3

1 Answers1

6

If directory recursion is desired, File::Find is probably both better and easier than rolling your own directory traversal logic. But because the question is mainly about parsing ls, I will cover that in some more detail.

Parsing ls output has a lot of complications. The proper way to do this is to process the directory yourself.

opendir(my $d, "/path/to/dir") or die "$!";
while ($item = readdir($d)) {
    if (-d $item) {
        print "dir $item\n";
    } else {
        print "notdir $item\n";
    }
}
closedir ($d);

There are many other file test operators besides -d. If you want more detailed control over each item, also look at stat.

tripleee
  • 175,061
  • 34
  • 275
  • 318