2012-02-28 80 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!。我可以简单地忽略那些不是文件的东西。

而且,你可能要检查的特殊情况。这是一个链接?它是一个硬链接还是软链接?怎么样特殊文件。这使事情变得更复杂一些。但是,基本知识在这里。