0

弗雷德又来这里了,我遇到了一个小问题,希望你们能帮助我。

我正在审查期中考试并查看我在这里找到的旧文件,我想让它工作。我在这里找不到它了,但我仍然有源代码,所以我会提出另一个问题。

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

这是脚本:

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

我已经检查了文件以确保它们都匹配,但仍然存在问题。如果有人可以帮助我,我将不胜感激!

4

1 回答 1

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断言您仅在哈希中包含常规文件。

于 2013-03-05T02:02:07.537 回答