2009-05-18 3 views
1

나는 폴더가 있고 그 안에 많은 하위 폴더가 있습니다. 그 하위 폴더에는 많은 .html 파일을 읽을 수 있습니다. 나는 그것을하기 위해 다음 코드를 작성했다. 상위 폴더와 첫 번째 하위 폴더를 열고 하나의 .html 파일 만 인쇄합니다. 그것은 오류를 보여줍니다 :여러 디렉토리를 읽고 Perl의 하위 디렉토리 내용을 읽으려면 어떻게해야합니까?

NO SUCH FILE OR DIRECTORY 

전체 코드를 변경하고 싶지 않습니다. 기존 코드의 수정은 나에게 도움이 될 것입니다.

use FileHandle; 
opendir PAR_DIR,"D:\\PERL\\perl_programes\\parent_directory"; 
while (our $sub_folders = readdir(PAR_DIR)) 
{ 
     next if(-d $sub_folders); 

     opendir SUB_DIR,"D:\\PERL\\perl_programes\\parent_directory\\$sub_folders"; 
     while(our $file = readdir(SUB_DIR)) 
     { 

     next if($file !~ m/\.html/i); 
      print_file_names($file);  
     } 
     close(FUNC_MODEL1);  
} 
close(FUNC_MODEL); 

    sub print_file_names() 
    { 
    my $fh1 = FileHandle->new("D:\\PERL\\perl_programes\\parent_directory\\$file") 
       or die "ERROR: $!"; #ERROR HERE 
    print("$file\n"); 
    } 
+0

팁 : "my"를 "our"로 사용하고 -w 옵션을 사용하여 perl을 실행하십시오 (가능하면 모두 사용하십시오). "my"를 사용했지만 엄격하지 않으면 "$ file"이 정의되지 않았으며 "$ file"이 선언되지 않았다고 엄격히 말하면 경고 메시지가 나타납니다. – araqnid

답변

4

당신은 print_file_names() 함수에서 제공 $file 매개 변수를 추출 아닙니다.

그것은해야한다 : 외부 루프에서

sub print_file_names() 
{ 
    my $file = shift; 
    ... 
} 

귀하의 -d 시험은 BTW, 너무 잘못된 보인다. 당신은 next if -d ...을 말하고 있습니다. 이것은 디렉토리에 대한 내부 루프를 건너 뛰는 것을 의미합니다. 이것은 여러분이 필요로하는 것과 완전히 반대되는 것으로 보입니다. 전혀 작동하지 않는 유일한 이유는 $file을 테스트 중이므로 전체 경로 이름이 아닌 경로와 관련된 파일 이름 만 있기 때문입니다. 또한

참고 :

Windows에서
  • 한 번 부모 디렉토리를 설정 경로 구분 기호로 /에 잘 대처하고 opendir(DIR, $path)
  • 대신 그
  • 사용 opendir($scalar, $path)에서 다른 경로를 도출

      nb : 테스트되지 않은 코드는 다음과 같습니다.

    1. +0

      ur 위대한 .... 고마워요 젠장 ... – User1611

      +1

      File :: Find - a)를 사용하지 않기 위해 나를 downvoted 모든 사람들을 위해 나는 opendir 등을 적절하게 사용하는 방법을 보여 주었고 b) 레벨 2에있는 파일들과 함께 디렉토리 레벨을 유지해야합니다. – Alnitak

      +0

      - 버그는 실제로 opendir 코드에 없기 때문에 print_file_names()에있었습니다 !! – Alnitak

      3

      를 사용하여 고려 유무 :

      use strict; 
      use warnings; 
      

      모든 스크립트의 상단에, 당신이이 같은 문제를 방지하고 많은 코드를 만들 것입니다 더 읽기 쉽습니다.

      당신은 여기에 대한 자세한 내용을보실 수 있습니다 : Perlmonks

      6

      귀하의 게시 된 코드는 방법 overcomplicated 보인다. File::Find::Rule을 확인하십시오. 그리고 그 코드의 대부분을 매우 적은 코드로 처리 할 수 ​​있습니다.

      use File::Find::Rule; 
      
      my $finder = File::Find::Rule->new()->name(qr/\.html?$/i)->start("D:/PERL/perl_programes/parent_directory"); 
      
      while(my $file = $finder->match() ){ 
          print "$file\n"; 
      } 
      

      내 말은 은 섹시하지 않습니까?!

      사용자는 사용자가 Depth = 2 항목 만 사용하기를 원한다고 말했습니다.

      use File::Find::Rule; 
      
      my $finder = File::Find::Rule->new()->name(qr/\.html?$/i)->mindepth(2)->maxdepth(2)->start("D:/PERL/perl_programes/parent_directory"); 
      
      while(my $file = $finder->match() ){ 
          print "$file\n"; 
      } 
      

      윌이 제한을 적용합니다.

      +1

      name ("* .html")은 그의 정규식과 동일한 파일과 일치하지 않습니다. 다행히도 name()은 globs뿐만 아니라 regexes도 허용합니다. 일치시킬 조건을 수정했습니다. – cjm

      +0

      그리고 이것은 그의 요구 사항과는 반대로 트리의 레벨 1과 3+에 파일 (존재해야 함)을 발견 할 것입니다. – Alnitak

      +0

      @Alnitak : 검색을위한 mindepth와 maxdepth를 쉽게 설정할 수 있습니다. –

      3

      당신은 그것을 강력하게 전체 코드를 변경해야 할 것 같습니다

      #!/usr/bin/perl 
      
      use strict; 
      use warnings; 
      
      use File::Find; 
      
      my $top = $ENV{TEMP}; 
      
      find({ wanted => \&wanted, no_chdir=> 1 }, $top); 
      
      sub wanted { 
          return unless -f and /\.html$/i; 
          print $_, "\n"; 
      } 
      
      __END__ 
      
      0

      여기에 파일 :: 찾기를 사용할 필요가 없습니다 하나의 방법입니다 :

      먼저 루트 디렉토리를 엽니을, readdir을 사용하여 모든 하위 폴더의 이름을 배열에 저장합니다.

      그런 다음 foreach 루프를 사용하십시오. 각 하위 폴더에 대해 루트 디렉터리와 폴더 이름을 연결하여 새 디렉터리를 엽니 다. readdir을 사용하여 파일 이름을 배열에 저장하십시오.

      마지막 단계는이 foreach 루프 안에 파일을 처리하기위한 코드를 작성하는 것입니다.

      저에게이 아이디어를 준 선생님 께 특별한 감사드립니다 :) 정말 잘했습니다!

      관련 문제