2009-05-18 226 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

提示:更喜歡使用「我的」到「我們的」,並運行perl -w選項(如果可能的話儘量使用「strict」)。如果使用「我的」但沒有嚴格的話,它會警告你「$ file」是未定義的,嚴格的說,它會在運行之前說「$ file」未聲明。 – araqnid 2009-05-18 18:15:16

回答

4

你不能提取的print_file_names()功能所提供的$file參數。

它應該是:

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

-d測試在外環看起來太錯了,順便說一句。你說next if -d ...這意味着它會跳過目錄的內部循環,這看起來與你所需要的完全相反。它唯一的原因是因爲你正在測試$file,它只是相對於路徑的文件名,而不是完整的路徑名。

還要注意:

  1. 的Perl在Windows科佩斯罰款/作爲路徑分隔符
  2. 設置你的父目錄一次,然後從
  3. 使用opendir($scalar, $path)獲得其他的路徑,而不是opendir(DIR, $path)

nb:未經測試的代碼如下:

use strict; 
use warnings; 
use FileHandle; 

my $parent = "D:/PERL/perl_programes/parent_directory"; 

my ($par_dir, $sub_dir); 
opendir($par_dir, $parent); 
while (my $sub_folders = readdir($par_dir)) { 
    next if ($sub_folders =~ /^..?$/); # skip . and .. 
    my $path = $parent . '/' . $sub_folders; 
    next unless (-d $path); # skip anything that isn't a directory 

    opendir($sub_dir, $path); 
    while (my $file = readdir($sub_dir)) { 
     next unless $file =~ /\.html?$/i; 
     my $full_path = $path . '/' . $file; 
     print_file_names($full_path);  
    } 
    closedir($sub_dir); 
} 
closedir($par_dir); 

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

你很棒....非常感謝你... – User1611 2009-05-18 15:28:03

+1

對於那些因爲不使用File :: Find而導致我失望的人 - a)我向他展示瞭如何正確使用opendir等等,以及b)他只指定了兩個目錄級別,文件都在2級。 – Alnitak 2009-05-18 19:20:52

3

請開始把考慮:

use strict; 
use warnings; 

在所有腳本的頂部,它會幫助你避免這樣的問題,使你的代碼更更具可讀性。

你可以閱讀更多關於它在這裏:Perlmonks

6

您發佈的代碼看起來過於複雜的方式。看看File::Find::Rule,你可以用很少的代碼完成大部分的繁重工作。我的意思是是不是性感?!

一位用戶評論說,您可能希望只使用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"; 
} 

將應用此限制。

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循環內的文件的代碼。

特別感謝我的老師給了我這個主意:)它確實運作良好!