2013-04-05 2 views
1

나는 재귀 적으로 디렉토리의 내용을 인쇄하는 스크립트를 작성했다. 그러나 각 폴더에 대해 경고를 인쇄합니다. 이 문제를 해결하는 방법?디렉토리 트리 경고

샘플 폴더 :

DEV #에서 cd ​​/ tmp를/테스트
dev에 # 1! -p -R
TEST2/
testfile 위
testfile2

./test2 :
testfile3
testfile4

내 코드 :

#!/usr/bin/perl 

use strict; 
use warnings; 

browseDir('/tmp/test'); 

sub browseDir { 
    my $path = shift; 
    opendir(my $dir, $path); 
    while (readdir($dir)) { 
     next if /^\.{1,2}$/; 
     if (-d "$path/$_") { 
      browseDir("$path/$_"); 
     } 
     print "$path/$_\n"; 
    } 
    closedir($dir); 
} 

출력 :

초기화되지 않은 값 $의

DEV # 펄 /tmp/cotest.pl
/tmp를/테스트/TEST2/testfile3
/tmp를/테스트/TEST2/testfile4
사용 _ /tmp/cotest.pl 라인에서 연결 (.) 또는 문자열에서 16
/tmp를/테스트/
/tmp를/테스트/testfile 위
/tmp를/테스트/testfile2

+0

'File :: Spec' <-이 모듈은'no_upwards()'func을 사용하여'.' 또는'..'와 같은 모든 디렉토리를 숨 깁니다. 예 :'@paths = File :: Spec-> no_upwards (@paths);' – gaussblurinc

+0

'while (readdir ($ dir)) {...}'을 사용하기 때문에 프로그램에'use 5.012; 이전 릴리스에서는 작동하지 않습니다. –

답변

1

당신이 월 그 코드를 시도 :

#!/usr/bin/perl 

    use strict; 
    use warnings; 

    browseDir('/tmp'); 

    sub browseDir { 
     my $path = shift; 
     opendir(my $dir, $path); 
     while (readdir($dir)) { 
      next if /^\.{1,2}$/; 
      print "$path/$_\n"; 
      if (-d "$path/$_") { 
       browseDir("$path/$_"); 
      } 
     } 
     closedir($dir); 
    } 

해당 오류는 당신이 사용하는 변수 $ 전에 browseDir()를 호출하기 때문에 _있어합니다.

+0

덕분에 작동합니다. 또한 $ _ 변수를 사용하지 않으면 경고가 인쇄되지 않습니다. 'while (my $ s = readdir ($ dir)) {...}' – Suic

+0

OP가 코드를 변경 했습니까? 나는 너와 그의 차이를 찾을 수 없다. – ikegami

+0

'print "$ path/$ _ \ n";'위로 이동 – Suic

1

당신은 browseDir를 호출하기 전에 $_에 값을 배치하고 당신은 값이 browseDir (합리적인 기대를) 호출 한 후있을 것으로 예상하지만, browseDir 변수 것을 수정합니다.

local $_;에서 browseDir까지만 추가하면 하위 종료 전에 변경 사항이 취소됩니다.

  • 도 최소한의 오류가 확인되지 않음 :

    질문에 관련없는

    , 여기에 세 가지 다른 문제입니다!

  • 딥 디렉터리를 탐색 할 디렉터리 핸들이 부족할 수 있습니다.
  • 파일 ".\n""..\n"을 필터링합니다.

수정 :

#!/usr/bin/perl 

use strict; 
use warnings; 

browseDir('/tmp/test'); 

sub browseDir { 
    my $path = shift; 

    opendir(my $dh, $path) or die $!; 
    my @files = readdir($dh); 
    closedir($dh); 

    for (@files) { 
     next if /^\.{1,2}z/; 
     if (-d "$path/$_") { 
      browseDir("$path/$_"); 
     } 

     print "$path/$_\n"; 
    } 
} 

마지막으로, 왜 File::Find::Rule처럼 당신에게 모듈을 사용하지 않는?

use File::Find::Rule qw(); 
print "$_\n" for File::Find::Rule->in('/tmp'); 

참고 : 5 전에.12, while (readir($dh))을 써야합니다. while (defined($_ = readdir($dh)))

+0

귀하의 의견에 감사드립니다, 나는 결코 $ _을 사용하지 않을 것입니다^_^ – Suic

+0

사실'while (readdir ($ dir)) {...}'은 ($ _ = readdir ($ dir))) {...}'현재 [5.12] (http://perldoc.perl.org/perlfunc.html#readdir-DIRHANDLE). [커밋] (http://perl5.git.perl.org/perl.git/commit/114c60ecb1f775ef1deb4fdc8fb8e3a6f343d13d) 불행히도 이것은 델타가되지 못했습니다. –

+0

@Brad Gilbert, 오, 정말! 그렇다면 문제는 '$ _'의 현지화가 부족하다는 것입니다. 재귀 호출은 부모가'$ _'에 보유하고있는 값을 망치고 있습니다. 업데이트 된 답변. – ikegami

1

File::Find 모듈을 사용하지 않는 이유는 무엇입니까? Perl 5.x부터 거의 모든 Perl 배포판에 포함되어 있습니다. 지저분한 방식으로 작동하는 것은 내가 좋아하는 모듈이 아니지만 좋은 일을합니다.

원하는 작업을 수행하고 원하지 않는 것을 필터링하는 wanted 서브 루틴을 정의합니다. 이 경우, 거의 모든 것을 인쇄하고 있으므로, 모두 wanted은 찾은 것을 인쇄합니다.

File::Find에는 파일 이름이 $File::Find::name이고 해당 파일의 디렉터리는 $File::Find::dir입니다. $_은 파일 자체이므로 테스트에 사용할 수 있습니다.

여기 당신이 원하는 기본적인 방법 :

use strict; 
use warnings; 
use feature qw(say); 

use File::Find; 

my $directory = `/tmp/test`; 

find (\&wanted, $directory); 

sub wanted { 
    say $File::Find::Name; 
} 

find 서브 루틴 내 wanted 기능을 넣어 선호하는, 그래서 그들은 함께있어. 이것은 위와 동일합니다 :

use strict; 
use warnings; 
use feature qw(say); 

use File::Find; 

my $directory = `/tmp/test`; 

find ( 
    sub { 
     say $File::Find::Name 
    }, 
    $directory, 
); 

좋은 프로그래밍은 서브 루틴에서 인쇄하지 않는다고 말합니다. 대신, 서브 루틴을 사용하여 데이터를 저장하고 반환해야합니다. 불행히도 find은 전혀 반환하지 않습니다. 별도의 wanted 서브 루틴을 원하는 경우,

use strict; 
use warnings; 
use feature qw(say); 

use File::Find; 

my $directory = `/tmp/test`; 
my @directory_list; 

find ( 
    sub { 
     push @directory_list, $File::Find::Name 
    }, $directory); 

for my $file (@directory_list) { 
    say $file; 
} 

또는 : 당신은 그들을 인쇄 나중에 파일 목록을 캡처하는 글로벌 배열을 사용하고, 필요

use strict; 
use warnings; 
use feature qw(say); 

use File::Find; 

my $directory = `/tmp/test`; 
my @directory_list; 

find (\&wanted, $directory); 
sub wanted { 
    push @directory_list, $File::Find::Name; 
} 

for my $file (@directory_list) { 
    say $file; 
} 

사실 그 내 원하는 서브 루틴은 서브 루틴에 국부적이지 않은 배열에 의존하기 때문에 내 find 호출 내에서 wanted 서브 루틴을 포함하는 것이 더 나은 이유입니다.

당신이 할 수있는 한 가지는 서브 루틴을 사용하여 원하는 것을 필터링하는 것입니다. 의 당신은 JPG 파일 만 관심이 있다고 가정 해 봅시다 : 원하는 서브 루틴 내 @directory_list 배열로 밀어 전에 원하지 않는 파일에 대한 next 어떻게하는지

use strict; 
use warnings; 
use feature qw(say); 

use File::Find; 

my $directory = `/tmp/test`; 
my @directory_list; 

find (\&wanted, $directory); 
sub wanted { 
    next unless /\.jpg$/i; #Skip everything that doesn't have .jpg suffix 
    push @directory_list, $File::Find::Name; 
} 

for my $file (@directory_list) { 
    say $file; 
} 

참고. 다시 말하지만, 나는 삽입 선호 :이 당신이 무엇을 요구 정확히 아니라는 것을 알고

find (sub { 
    next unless /\.jpg$/i; #Skip everything that doesn't have .jpg suffix 
    push @directory_list, $File::Find::Name; 
} 

,하지만 당신은 아직 작성하지 않은 경우 그냥합니다 (Find::File 모듈에 대해 알려 펄 모듈을 소개하고 싶었다 Perl에 많은 기능을 추가 할 수있는 이들에 대해 알고 있어야한다.

관련 문제