如何比较两个目录及其在perl中的文件 [英] How to compare two directories and their files in perl
问题描述
我正在审查中期,并审查一个老的文件我在这里发现,我想让它工作。我不能在这里找到它,但我仍然有源代码,所以我会提出另一个问题。
这是他的任务:
编写一个perl脚本,它将比较两个目录中常规文件中的差异。所有具有相同名称的常规文件应该使用unix函数/ usr / bin / diff -q进行测试,这将确定它们是否相同。在dir1中没有类似命名的文件的文件将在字符串<<<而dir2中没有相应dir1条目的文件将以字符串>>>作为前缀。如果两个文件具有相同的名称但不同,则文件名将被><。
以下是脚本:
#!/ usr / bin / perl -w
使用File :: Basename;
@ files1 =`/ usr / bin / find $ ARGV [0] -print`;
chop @ files1;
@ files2 =`/ usr / bin / find $ ARGV [1] -print`;
chop @ files2;
语句:
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 eqFiles $ files1 [$ i]和$ files2 [$ x] different){
print< $ file1> \\\
;
next语句;
} else {
print> $ file1< \\\
;
}
} else {
if(!-e$ files1 [$ i] / $ file2){print>>> $ file2\\\
;}
unless(-e$ files2 [$ x] / $ file1){print<<< $ file1\\\
;}
}
}
}
这是输出:
> file2<
>>>> file5
<<< file1
输出应为:
> file1<
> file2<
<<< file4
>>>> file5
我已经检查了文件,以确保它们都匹配,但仍然有问题。
首先,请务必使用这些:
使用strict;
使用警告;
它有一个简短的学习曲线,但它们远远弥补了它的长期。
一些备注:
- 您应该使用
File :: Find
模块,而不是使用系统呼叫。 - 在数组索引1处启动循环。在perl中,第一个数组索引为0.因此,跳过第一个元素。
- 您的循环条件错误。
@files> = $ x
表示您将迭代到超过max索引(通常)。你想要$ x< @files
或$ x< = $#files
。 - c> 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);
-efoo / bar.html / bar.html; #不计算
查找,假设您只想匹配相同的文件名和缺少的文件名:
use strict;
使用警告;
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);
为我的$文件(@all){
my $ result;
if($ files1 {$ file}&& $ files2 {$ file}){#文件存在于两个dirs中
$ result = qx(/ usr / bin / diff -q $ files1 { $ file} $ files2 {$ file});
#... etc
} elsif($ files1 {$ file}){#文件只存在于dir1
} else {#文件只存在于dir2
}
}
子程序 $ _
代表基本名称, $ File :: Find :: name
适用于 diff
)。 -f
检查将断言您只将常规文件包含在哈希中。
Fred here again with a little issue I'm having that I hope you guys can help me with.
I'm reviewing for midterms and going over an old file I found on here and I wanted to get it working. I can't find it on here anymore but I still have the source code so I'll make another question on it.
So here was his assignment: Write a perl script that will compare two directories for differences in regular files. All regular files with the same names should be tested with the unix function /usr/bin/diff -q which will determine whether they are identical. A file in dir1 which does not have a similarly named file in dir2 will have it's name printed after the string <<< while a file in dir2 without a corresponding dir1 entry will be prefixed with the string >>>. If two files have the same name but are different then the file name will be surrounded by > <.
Here is the script:
#!/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";}
}
}
}
This is the output:
> file2 <
>>> file5
<<< file1
The output should be:
> file1 <
> file2 <
<<< file4
>>> file5
I already checked the files to make sure that they all match and such but still having problems. If anyone can help me out I would greatly appreciate it!
First off, always use these:
use strict;
use warnings;
It comes with a short learning curve, but they more than make up for it in the long run.
Some notes:
- You should use the
File::Find
module instead of using a system call. - You start your loops at array index 1. In perl, the first array index is 0. So you skip the first element.
- Your loop condition is wrong.
@files >= $x
means you will iterate to 1 more than max index (normally). You want either$x < @files
or$x <= $#files
. - You should use
chomp
, which is a safer version ofchop
. - Altering the arrays you are iterating over is a sure way to cause yourself some confusion.
- Why use
if (! -e ...)
and thenunless (-e ...)
? That surely just adds confusion.
And this part:
$file1 = basename($files1[$i]);
...
if ( !-e "$files1[$i]/$file2" )
Assuming @files1
contains file names and not just directories, this will never match anything. For example:
$file2 = basename("dir/bar.html");
$file1 = basename("foo/bar.html");
-e "foo/bar.html/bar.html"; # does not compute
I would recommend using hashes for the lookup, assuming you only want to match against identical file names and missing file names:
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
}
}
In the find()
subroutine, $_
represents the base name, and $File::Find::name
the name including path (which is suitable for use with diff
). The -f
check will assert that you only include regular files in your hash.
这篇关于如何比较两个目录及其在perl中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!