2012-02-28 76 views
1

目錄我是新來使用Perl所以原諒我noobness,比較兩個使用Perl

這裏就是我打算做的。

​​

DIR1 & DIR2是目錄名。

腳本dirComp.pl應確定在DIR1 & DIR2內容是否相同或不同。

我想出了一個算法

Store all the contents of dir1(recursively) in a list 
Store all the contents of dir2 in another list 
Compare the two list, if they are same - dir1 & dir2 are same else not. 

my @files1 = readdir(DIR1h); 
my @files2 = readdir(DIR2h); 

    # Remove filename extensions for each list. 

     foreach my $item (@files1) { 
     my ($fileName, $filePath, $fileExt) = fileparse($item, qr/\.[^.]*/); 
     $item = $fileName; 
     } 


     foreach my $item (@files2) { 
     my ($fileName, $filePath, $fileExt) = fileparse($item, qr/\.[^.]*/); 
     $item = $fileName; 
     } 

我不能遞歸遍歷子目錄在上面代碼的幫助下給定的目錄。任何幫助,將不勝感激。

編輯:使用文件:DirCompare

#!/usr/bin/perl -w 

use File::DirCompare; 
use File::Basename; 

if ($#ARGV < 1) 
{ 
     &usage; 
} 

my $dir1 = $ARGV[0]; 
my $dir2 = $ARGV[1]; 

File::DirCompare->compare($dir1,$dir2,sub { 
     my ($a,$b) = @_; 
     if (!$b) 
     { 
       printf "Test result:PASSED.\n"; 
       printf "Only in %s : %s\n", dirname($a), basename($a); 
     }elsif (!$a) { 
       printf "Test result:PASSED.\n"; 
       printf "Only in %s : %s\n", dirname($b), basename($b); 
     }else { 
       printf "Test result:FAILED.\n"; 
       printf "Files $a and $b are different.\n"; 
     } 
}); 

我有如下的目錄結構,

dir1/     dir2/ 
    --file1.txt   --file1.txt 
    --file2.txt   --file2.txt 
    --file3.cpp   --file3.cpp 

我面對測試結果:失敗。其結果是必須已經通過。任何人都可以請糾正我?

感謝

回答

2

我推薦使用File::DirCompare模塊來代替。 )它需要遍歷目錄結構的所有努力 - 您只需要定義應如何檢查目錄(是否應該比較文件內容等)

+0

我基本上試圖模仿UNIX的diff -r命令嗎? – Kelly 2012-02-28 08:49:28

5

您使用File::DirCompare提供的示例按預期工作。

記住回調調用子程序,每獨特文件中的每個目錄和每對文件這在他們的內容不同的。具有相同的文件名是不夠的,每個文件的每個目錄中的內容必須完全一樣好。

此外,你報告情況「通過」是不是在所有成功(由您定義),因爲它們的細節,其中一個文件存在於一個目錄,而不是其他的情況:這意味着目錄'的內容不相同。

這應該是更接近你想要什麼:

#!/usr/bin/perl 

use strict; 
use warnings; 

use File::DirCompare; 
use File::Basename; 

sub compare_dirs 
{ 
    my ($dir1, $dir2) = @_; 
    my $equal = 1; 

    File::DirCompare->compare($dir1, $dir2, sub { 
    my ($a,$b) = @_; 
    $equal = 0; # if the callback was called even once, the dirs are not equal 

    if (!$b) 
    { 
     printf "File '%s' only exists in dir '%s'.\n", basename($a), dirname($a); 
    } 
    elsif (!$a) { 
     printf "File '%s' only exists in dir '%s'.\n", basename($b), dirname($b); 
    } 
    else 
    { 
     printf "File contents for $a and $b are different.\n"; 
    } 
    }); 

    return $equal; 
} 

print "Please specify two directory names\n" and exit if (@ARGV < 2); 
printf "%s\n", &compare_dirs($ARGV[0], $ARGV[1]) ? 'Test: PASSED' : 'Test: FAILED'; 
0

你可能想嘗試醇」 File::Find。這不是我最喜歡的模塊。 (這是它的工作方式只是時髦的),但是你的目的,它可以讓你很容易地找到兩個目錄中的所有文件,並進行比較。這裏有一個簡單的例子:

use strict; 
use warnings; 
use feature qw(say); 
use Digest::MD5::File qw(file_md5_hex); 

use File::Find; 

use constant { 
    DIR_1 => "/usr/foo", 
    DIR_2 => "/usr/bar", 
}; 

my %dir_1; 
my %dir_2; 

find (sub { 
     if (-f $File::Find::name) { 
      $dir_1{$File::Find::name} = file_md5_hex($File::Find::name); 
     } 
     else { 
      $dir_1($file::Find::name} = "DIRECTORY!"; 
     } 
    }, DIR_1); 

find (sub { 
     if (-f $File::Find::name) { 
      $dir_2{$File::Find::name} = file_md5_hex($File::Find::name); 
     } 
     else { 
      $dir_2($file::Find::name} = "DIRECTORY!"; 
     } 
    }, DIR_2); 

這將創建在每個目錄中的文件名鍵入兩個散列。我用Digest::MD5::File創建一個MD5校驗。如果兩個文件之間的差異檢驗,我所知道的文件不同(雖然我不知道在哪裏)。

現在你要做的三兩件事:通過%dir_1

  1. 去看看是否有在%dir_2的等價的鍵。如果沒有相同的密鑰,則知道%dir_1中存在文件,而不是%dir_2
  2. 如果每個散列中都有相同的密鑰,請檢查md5校驗和是否一致。如果他們這樣做,那麼,文件匹配。如果他們不是不同的話。你不能說他們有什麼不同,但它們有所不同。
  3. 最後,經過%dir_2和檢查,看看是否有在%dir_1的等價的鍵。如果有的話,什麼都不要做。如果沒有,則表示%dir_1中的文件不在%dir_2中。

警告只是一個字:該鍵詮釋這兩個散列將不匹配。進行比較時,您必須將其中一個轉換爲另一個。例如,你有兩個文件:

/usr/bar/my/file/is/here.txt 
/usr/foo/my/file/is/here.txt 

正如你所看到的,my/file/is/here.txt在這兩個目錄都存在,但在我的代碼,兩個散列將有兩個不同的密鑰。您可以修復這兩個子例程以從文件路徑的前面剝離目錄名稱,或者在進行比較時將其轉換爲另一個。我不想通過全面測試。 (我寫的代碼片段在我的測試中有效),所以我不能100%確定要做什麼才能確保找到匹配的密鑰。

哦,另一個警告:我拿起所有項目,而不僅僅是文件。對於目錄,我可以檢查散列鍵是否等於DIRECTORY!。我可以簡單地忽略那些不是文件的東西。

而且,你可能要檢查的特殊情況。這是一個鏈接?它是一個硬鏈接還是軟鏈接?怎麼樣特殊文件。這使事情變得更復雜一些。但是,基本知識在這裏。