2014-03-02 25 views
0

所以我知道你可以在子程序中使用opendir打開目錄,然後使用readdir來讀取當前工作目錄中的所有文件,然後將所有文件推送到一個數組中。如果它是一個文件,則通過該數組,然後打印該文件或將該文件推入一個新數組,否則如果它是一個目錄,則遞歸地再次調用該子例程。我不明白的是在這裏指定深度。任何幫助是極大的讚賞。在Perl中如何使用遞歸來搜索目錄和子目錄並指定深度?


以下是我來到你的幫助的解決方案:

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 
+0

相關問題:http://stackoverflow.com/q/13374829/133939 – Zaid

回答

0

你可以傳遞一個參數叫,說,level的遞歸函數,調用該函數爲recurse(level+1, subdirectory)

無論如何,最好使用專門的庫如File::Find來執行此任務。

+0

你可以看看上面的代碼我我仍然困惑在哪裏做深度的地方,我會把條件放在哪裏。非常感謝你的幫助。 – user2344516

+1

任何你想要的地方,但可能接近'read_dir'的開始。 (如果$ level> 5,'返回'') – ikegami

0

不過,這是很好的鍛鍊和追逐遠離懶惰......

<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>