如何在perl中比较两个目录及其文件

时间:2013-03-05 01:21:05

标签: perl file compare directory

弗雷德在这里再次提出一个问题,我希望你们可以帮助我。

我正在检查midterms并查看我在这里找到的旧文件,我想让它正常工作。我在这里找不到了,但我仍然有源代码,所以我会再提出一个问题。

所以这是他的任务: 编写一个perl脚本,它将比较两个目录中常见文件的差异。应使用unix函数/ usr / bin / diff -q测试具有相同名称的所有常规文件,这将确定它们是否相同。 dir1中的文件在dir2中没有类似命名的文件,它将在字符串<<<< dir2中没有相应dir1条目的文件将以字符串>>>为前缀。如果两个文件具有相同的名称但不同,则文件名将被>包围。 &LT ;.

这是脚本:

#!/usr/bin/perl -w 
use File::Basename;

@files1 = `/usr/bin/find $ARGV[0] -print`;
chop @files1;
@files2 = `/usr/bin/find $ARGV[1] -print`;
chop @files2;

statement:
for ($i=1; @files1 >= $i; $i++) {
    for ($x=1; @files2 >= $x; $x++) {

        $file1 = basename($files1[$i]);
        $file2 = basename($files2[$x]);

        if ($file1 eq $file2) {
            shift @files1;
            shift @files2;
            $result = `/usr/bin/diff -q $files1[$i] $files2[$x]`;
            chop $result;

            if ($result eq "Files $files1[$i] and $files2[$x] differ") {
                print "< $file1 >\n";
                next statement;
        } else {
                print "> $file1 <\n";
            }
        } else  {
            if ( !-e "$files1[$i]/$file2") { print ">>> $file2\n";}
            unless ( -e "$files2[$x]/$file1") { print "<<< $file1\n";}
        }
    }
}

这是输出:

> file2 <
>>> file5
<<< file1

输出应为:

> file1 <
> file2 <
<<< file4
>>> file5

我已经检查了文件,以确保它们都匹配,但仍有问题。如果有人能帮助我,我会非常感激!

1 个答案:

答案 0 :(得分:3)

首先,请始终使用这些:

use strict;
use warnings;

它有一个简短的学习曲线,但从长远来看,它们不仅可以弥补它。

一些注意事项:

  • 您应该使用File::Find模块而不是使用系统调用。
  • 您在数组索引1处开始循环。在perl中,第一个数组索引为0.因此,您跳过第一个元素。
  • 您的循环条件错误。 @files >= $x表示您将迭代到超过最大索引1(通常)。您需要$x < @files$x <= $#files
  • 您应该使用chomp,这是chop的更安全版本。
  • 改变你正在迭代的数组是一种让你自己感到困惑的可靠方法。
  • 为什么要使用if (! -e ...)然后使用unless (-e ...)?这肯定会增加混乱。

这一部分:

$file1 = basename($files1[$i]);
...
if ( !-e "$files1[$i]/$file2" )

假设@files1包含文件名而不仅仅是目录,这将永远不会匹配任何内容。例如:

$file2 = basename("dir/bar.html");
$file1 = basename("foo/bar.html"); 
-e "foo/bar.html/bar.html";         # does not compute

我建议使用哈希进行查找,假设您只想匹配相同的文件名和缺少文件名:

use strict;
use warnings;
use File::Find;
use List::MoreUtils qw(uniq);

my (%files1, %files2);
my ($dir1, $dir2) = @ARGV;

find( sub { -f && $files1{$_} = $File::Find::name }, $dir1);
find( sub { -f && $files2{$_} = $File::Find::name }, $dir2);

my @all = uniq(keys %files1, keys %files2);

for my $file (@all) {
    my $result;
    if ($files1{$file} && $files2{$file}) { # file exists in both dirs
        $result = qx(/usr/bin/diff -q $files1{$file} $files2{$file});
        # ... etc
    } elsif ($files1{$file}) {              # file only exists in dir1
    } else {                                # file only exists in dir2
    }
}

find()子例程中,$_表示基本名称,$File::Find::name表示包含路径的名称(适用于diff)。 -f检查将断言您只在哈希中包含常规文件。

相关问题