2014-03-02 6 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>