In Perl how to use recursion to search directories and sub directories and specify the depth?

徘徊边缘 提交于 2019-12-11 19:34:41

问题


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

回答1:


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.




回答2:


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>


来源:https://stackoverflow.com/questions/22128738/in-perl-how-to-use-recursion-to-search-directories-and-sub-directories-and-speci

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!