Harry Putnam wrote:
I need to do some matching of filenames in two top level directories.
We expect to find a number of cases where the endnames ($_) are the
same in both hierarchies but the full name is different.
base1/my/file
base2/my/different_path/file
I've made hashes of the file names in two top level directories:
I've assembled the hashes using File::Find. We sort them first by
matching the base directory to the top directories passed in.
My first impulse wast to do it by matching the endnames (or value) in
one hash to any matching endname (value) in the other. There are
several more actions that follow (not coded yet) but That's a lot of
spinning...
I'm thinking there are better ways to do that. So .. the script below
does it the hard way, with all that spinning. Can anyone suggest
another way?
------- --------- ---=--- --------- --------
#!/usr/local/bin/perl
use strict;
use warnings;
use File::Find;
use Cwd;
my $r1 = shift;
my $r2 = shift;
( my ( $r1, $r2 ) = @ARGV ) == 2
or die "usage: $0 dir1 dir2\n";
my %r1h;
my %r2h;
my $r1hkcn = 0;
my $r2hkcn = 0;
find(
sub {
## For use in guaranteeing the -f command uses the
## right path
my $dir = getcwd;
The current working directory is already in $File::Find::dir
if (-f $dir . '/'. $_) {
return unless -f;
## Determine if base dir matches r1 or r2
(my $base) = $File::Find::name =~ m/^(\.*\/*\/[^\/]+)\//;
Instead of all the "leaning toothpicks" use a different delimiter:
(my $base) = $File::Find::name =~ m!^(\.*/*/[^/]+)/!;
if ($r1 eq $base) {
$r1h{$File::Find::name} = $_;
$r1hkcn++;
if ($r1hkcn == 1) {
print "v:$File::Find::name k:$_\n";
}
} else {
$r2h{$File::Find::name} = $_;
$r2hkcn++;
if ($r2hkcn == 1) {
print "v:$File::Find::name k:$_\n";
}
}
}
},
$r1,$r2
);
my ($r1full,$r1end);
while (($r1full,$r1end) = each(%r1h)) {
foreach my $key (keys %r2h) {
No need for a loop there, just use exists():
if ( exists $r2h{ $rlend } ) {
print "$r2h{$rlend} MATCHES $r1end\n";
if ($r2h{$key} eq $r1end) {
print "$r2h{$key} MATCHES $r1end\n";
}
}
}
Perhaps you want something like:
#!/usr/local/bin/perl
use strict;
use warnings;
use File::Find;
( my ( $r1, $r2 ) = @ARGV ) == 2
or die "usage: $0 dir1 dir2\n";
my %data;
find sub {
return unless -f;
$data{ $_ }{ $r1 }++;
}, $r1;
find sub {
return unless -f;
$data{ $_ }{ $r2 }++;
}, $r2;
while ( my ( $file, $dir ) = each %data ) {
my @dirs = keys %$dir;
if ( @$dirs == 2 ) {
print "$dirs[0] MATCHES $dirs[1]\n";
}
}
__END__
John
--
The programmer is fighting against the two most
destructive forces in the universe: entropy and
human stupidity. -- Damian Conway
--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/