使用Perl比较两个目录

时间:2012-02-28 07:20:06

标签: perl

我是Perl的新手,请原谅我的无知,

这就是我打算做的事情。

$ perl dirComp.pl dir1 dir2

dir1& dir2是目录名称。

脚本dirComp.pl应该识别dir1和amp;中的内容。 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

我正面临测试结果:失败。结果必须通过。谁能请你纠正我?

由于

3 个答案:

答案 0 :(得分:5)

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

请记住,每个目录中的每个唯一文件以及内容不同的文件对都会调用回调子例程。拥有相同的文件名是不够的,每个目录中每个文件的内容也必须完全相同。

此外,报告“PASSED”的情况根本不是成功的(根据您的定义),因为它们详细说明了其中一个目录中存在文件但不存在另一个目录的情况:表示目录'内容不一样。

这应该更接近你想要的东西:

#!/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';

答案 1 :(得分:2)

我建议改用File::DirCompare模块。 )它需要遍历目录结构的所有艰苦工作 - 你只需要定义如何检查目录(如果sub比较文件内容等)。

答案 2 :(得分: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校验和。如果两个文件之间的校验和不同,我知道文件不同(虽然我不知道在哪里)。

现在你必须做三件事:

  1. 浏览%dir_1,查看%dir_2中是否有等效的密钥。如果没有等效密钥,您知道%dir_1而不是%dir_2中存在文件。
  2. 如果每个哈希中都有一个等效的密钥,请检查md5校验和是否一致。如果他们这样做,则文件匹配。如果他们不这样做他们不同。你不能说他们的不同之处,但他们有所不同。
  3. 最后,浏览%dir_2并检查%dir_1中是否有等效的密钥。如果有,什么都不做。如果没有,则表示%dir_1中的文件不在%dir_2中。
  4. 只需提醒一句:这两个哈希 中的键与 不匹配。在进行比较时,您必须将一个转换为另一个。例如,您将有两个文件:

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

    如您所见,my/file/is/here.txt存在于两个目录中,但在我的代码中,两个哈希将具有两个不同的键。您可以修复两个子例程以从文件路径的前面剥离目录名称,或者在进行比较时将一个子例程转换为另一个子例程。我不想经历一次完整的测试。 (我编写的代码在我的测试中有效),所以我不能100%确定你必须做些什么才能确保找到匹配的密钥。

    哦,另一个警告:我拿起所有条目,而不只是文件。对于目录,我可以检查哈希键是否等于DIRECTORY!。我可以简单地忽略那些不是文件的东西。

    并且,您可能想要检查特殊情况。这是一个链接吗?它是硬链接还是软链接?某种特殊文件怎么样?这使得事情变得更加复杂。但是,基础知识就在这里。