"John W. Krahn" <jwkr...@shaw.ca> writes:
>> 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

This should have been clarified better as Uri has noted...
The match was to be the part in brackets against the other part in
brackets below:

   base2/my/different_path/[file]
   base1/my/[file]

so the hashes were to have these pairs:

   for base2:
    file => base2/my/different_path/file
or: ($_) =>   ($File::Find::name)  

   for base1:
    file => base1/my/file
or: ($_) => ($File::Find::name)  
 
And the matching would be 
  each  $value from base1 hash matched against
   all  $values from base2 hash.

Where a match occurs... extract that value from base2  

There may be several or none.  Further processing would follow on the
matches, and further processing again on multiple matches, that code
is not present yet.

I posted my effort at digging out the matches.
   
I see the way you did it, even though not the exact results I was
after is 100s of percent better way to write it.

I'm curious though if the overhead is different in your compact code
compared to mine. That is, if all that spinning through dir2:
,----
|   my ($r1full,$r1end);
|  while (($r1full,$r1end) = each(%r1h)) {
|    foreach my $key (keys %r2h) {
`----

 is more costly than your compact example: 

,----
|     if ( exists $r2h{ $rlend } ) {
|        print "$r2h{$rlend} MATCHES $r1end\n";
`----

In other words is the perl interpreter working harder in one case?

[...]

Harry wrote:

>> #!/usr/local/bin/perl
>>   use strict;
>> use warnings;
>>
>> use File::Find;
>> use Cwd;
>>
>>  my $r1 = shift;
>>  my $r2 = shift;

John K. replied:

> ( my ( $r1, $r2 ) = @ARGV ) == 2
>     or die "usage: $0 dir1 dir2\n";

That is a nice compact way of putting it.  Thanks

[...]

Harry wrote:
>> find(
>>   sub {
>>     ## For use in guaranteeing the -f command uses the
>>     ## right path
>>     my $dir = getcwd;
>>       if (-f $dir . '/'. $_) {
>

John K. replied:
> The current working directory is already in $File::Find::dir
[...]
>         return unless -f;


What made me go with Cwd was tests I tried during tinkering where I
got the apparently wrong headed notion that $File::Find::dir didn't do
what I wanted.

After getting unexpected `undefined' errors, I did a less elaborate
and uglier test like this one (now trying to use (some) or your style of
writing a find() function):
------- 8< snip ---------- 8< snip ---------- 8<snip ------- 
cat ex1.pl
#!/usr/local/bin/perl

use strict;
use warnings;
use File::Find;
use Cwd;

my $topdir2recurse = shift;

## Trying to use JKs' notation

my $cnt1 = 0;
find  sub {
        if(-f $File::Find::name){
          $cnt1++;
        }
      },$topdir2recurse;

print "Finished 1st recurse, count was <$cnt1>\n";
# -------       -------       ---=---       -------      ------- 
my $cnt2 = 0;
find  sub {
       my $dir = getcwd;
       if(-f $dir . '/' . $_){
          $cnt2++;
       }
      },$topdir2recurse;

print "Finished 2nd recurse, count was <$cnt2>\n";

            __END__
-------        ---------       ---=---       ---------      -------- 
run ex1.pl ./dir1
  Finished 1st recurse, count was <0>
  Finished 2nd recurse, count was <625>
-------        ---------       ---=---       ---------      -------- 
I'm sure my test is invalid since you've shown that $File::Find:;dir
is all I needed.  But not sure I see why it works in one case but not
this case.  (Something wrong with the example no doubt)


>>         ## 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!^(\.*/*/[^/]+)/!;

Thanks... point taken.

[...] snipped great example code.

(
Note: There are apparently some typos or such in there, I'm trying to
figure out. As posted it doesn't actually work when fed 2 directories:

  jkex.pl ./dir1 ./dir2

  Global symbol "$dirs" requires explicit package name at ./jkex.pl
  line 25.
  Execution of ./jkex.pl aborted due to compilation errors.

And if I create a global symbol for $dirs (my $dirs;)

  jkex.pl ./dir1 ./dir2
 <after a few moments pause>

  Can't use an undefined value as an ARRAY reference at ./jkex.pl line
  26.
)

John offered:
> Perhaps you want something like:

[...] script snipped

Yes, once I get it working... and figure out what is actually going on
in that compact code it is the kind of code I'd like to be able to
dash off (and read) some day.

I don't see (yet) what is supposed to be happening here.  There is a
lot happening that isn't obvious to me.

       $data{ $_ }{ $r2 }++
   $data{ $_ } .. (ok thats what I called the end name)
 
Are {} playing the role of rgx delimiters in `{ $r2 }'

Or is it the same as saying:
   $data{ $_ } eq $r2

I'm not sure what roll the `++' plays there either.    


-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to