2012-02-28 13 views
1

私はPerlに新しいので、私のnoobnessをお待ちしております。Perlを使用して2つのディレクトリを比較する

私は何をするつもりです。

​​

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; 
     } 

が出ています。どんな助けもありがとう。

EDIT:使用したファイル:FAILED: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

5

File::DirCompareを使用して指定した例が意図したとおりに動作します。

コールバックサブルーチンが各ディレクトリで、その内容が異なるファイルのすべてのペアごとユニークファイルに対して呼び出されることに注意してください。同じファイル名では不十分ですが、各ディレクトリの各ファイルの内容はまったく同じでなければなりません。

さらに、 "PASSED"と報告されたケースは、ファイルがディレクトリの1つに存在し、それ以外のものに存在しないケースを詳述しているため、(あなたの定義によって)全く成功しません。ディレクトリの内容は同一ではありません。

これは、あなたが望むものに近いようになります。

#!/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をしようとする場合があります。私のお気に入りのモジュールではありません。 (それはうまく動作します)しかし、目的のために、2つのディレクトリにあるすべてのファイルを簡単に見つけて比較することができます。簡単な例を示します。

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); 

これにより、各ディレクトリのファイル名で2つのハッシュが作成されます。私はDigest::MD5::Fileを使ってMD5チェックサムを作成しました。 2つのファイルのチェックサムが異なる場合は、ファイルが異なることがわかります(ただし、どこにはわからない)。%dir_1を通じて

  1. 移動し、%dir_2で同等のキーがありますかどうかを確認:

    は今、あなたは3つのことを行う必要があります。同等のキーがない場合は、ファイルが%dir_1で、%dir_2ではないことがわかります。

  2. 各ハッシュに同等のキーがある場合は、md5チェックサムが一致するかどうかを確認してください。そうした場合、ファイルは一致します。彼らが違うなら、彼らは違う。彼らはどこが違うかは言えませんが、それらは異なります。
  3. 最後に%dir_2にアクセスし、同等のキーが%dir_1にあるかどうかを確認してください。もしあれば、何もしないでください。存在しない場合、%dir_1には%dir_2にないファイルがあることを意味します。

警告の言葉だけは:キーは、これら2つのハッシュがとは一致しませんint型。あなたは比較を行うときに、一方を他方に変えなければならないでしょう。たとえば、あなたのように2つのファイルがあります:あなたが見ることができるように

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

my/file/is/here.txtは、両方のディレクトリに存在しますが、私のコードでは、2つのハッシュは、二つの異なるキーを持つことになります。 2つのサブルーチンを修正して、ディレクトリ名をファイルパスの先頭から取り除くか、または比較するときに、一方を他方に変換します。私は完全なテストを実行したくなかった。 (私が書いたコードのほうが私のテストでうまくいきます)、一致するキーが見つかるようにするために何をしなければならないか100%は確信していません。

もう1つの警告:ファイルだけでなく、すべてのエントリを取得します。ディレクトリについては、ハッシュキーがDIRECTORY!に等しいかどうかを確認することができます。私は単にファイルではないすべてを無視することができます。

また、特殊なケースを確認することもできます。これはリンクですか?それはハードリンクかソフトリンクですか? 特殊ファイルの場合はどうですか。それは物事をもう少し複雑にします。しかし、基本はここにあります。

関連する問題