문제

So I know you can in the subroutine, open the directory using opendir, then use readdir to to read all the files in the current working directory, then push all the files into an array. Go through the array if it is a file then print the file or push that file into a new array else if it is a directory recursively call the subroutine again. What I don't understand is where in here would I specify the depth. Any help is greatly appreciated.


The following is the solution I arrived at with your help:

 read_dir('test', 1);

 sub read_dir {
    $dir = shift;
    $level = shift;

    chdir ($dir);
    opendir(DIR, '.') or die "Can't open $dir: $!";
    @filesarray = readdir (DIR) or die;
    closedir(DIR);
    my @files;
    foreach my $file (@filesarray) {
        if (-f $file && $file =~ /\.txt$/i){
              push @files, $file;
            } ## end of if

        elsif (-d $file) {
              next if ($file eq ".");
              next if ($file eq "..");
              $dir = $file;
              read_dir($dir, $level+1); ## QUESTION IS HERE?????
         } ## end of elsif
    } ## end of foreach

    foreach my $file1 (@files) {
         print "$file1\n";
    }
} ## end of sub read_dir
도움이 되었습니까?

해결책

You can pass a parameter to the recursing function called, say, level, and call the function as recurse(level+1, subdirectory).

Anyway, it's best to use a specialized library like File::Find for this task.

다른 팁

Still, it's good exercise and chases away the laziness...

<pre><code>

#!/usr/bin/perl
use DirFind;
my $max = shift(@ARGV);
my $dir = shift(@ARGV);
my $filter = shift(@ARGV);
my %args = (
    maxdepth => $max,
    dirs => $dir,
    filter => $filter
);
# recursive
my $df_r = DirFind->new(%args);
print join("\n", $df_r->reader_r()->result_files()),"\n\n";
exit;

package DirFind;

#
# essentially mimic find
#

#
# we'll be storing things away so we want an object
#
sub new {
    my ($class, @rest) = @_;
    my $self = bless({@rest}, $class);
    # for the sake of all things being equal manufacture the level
    # and translate to listref context so that the new() args can
    # be just the simpler dirs => path
    my $dir = $self->{dirs};
    $self->{dirs}->[0] = join(' ', $dir, 0);
    return $self;
}

#
# with tail recursion we need to store the filter and depth in new()
#
sub reader_r {
    my ($self) = @_;
    my ($d, $lvl) = split(' ', shift(@{$self->{dirs}}));
    # no more directories
    return if (!defined($d) || !defined($lvl));
    return if ($lvl == $self->{maxdepth});
    $lvl++;
    # making the regex a bit more protected
    my $filter = $self->{filter};
    opendir(my $dh, $d);
    my @basefiles = readdir($dh);
    closedir($dh);
    foreach my $f (@basefiles) {
        next if ($f =~ /^\.{1,2}$/);
        my $file = join('/', $d, $f);
        # implicitly skip symlinks
        push(@{$self->{dirs}}, join(' ', $file, $lvl)) if (-d $file);
        if (-f $file) {
        if (defined($filter)) {
            next unless ($file =~ m!$filter!);
            push(@{$self->{files}}, $file);
        }
        }
    }
    if (@{$self->{dirs}}) {
        $self->reader_r();
    }
    # for chaining
    return $self;
}

#
# the recursive form requires the additional call to get the results
# no we chain them
#
sub result_files {
    my ($self) = @_;
    return wantarray? @{$self->{files}}: $self->{files};
}
1;
</code></pre>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top