For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > March 2004 > Search for a file pattern in a directory tree recursively









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Search for a file pattern in a directory tree recursively
Rajesh Dorairajan

2004-03-26, 11:14 pm

Hello All,

I went through all the documentation and previous mail posts about
File::Find and finally decided I needed some help.

I've a directory structure I need to parse. The directory contains
subdirectories with filenames such as

full094382.db
full483292.db

Now, I need to parse through each subdirectory and pick up the name of the
file that was MODIFIED MOST RECENTLY. I do have a sort of a code to start
with.

use strict;
use warnings;

$\ = "\n";

use File::Find;

my $localdir = 'C:/docs';
my @files;

find(
sub { push ( @fullcrls, $File::Find::name ) if /^(full)\w*(\.db)$/ },
$localdir );

foreach ( @fullcrls ) {
print;
}

However, I am not able to figure how to filter out the repeat entries in a
sub-directory such as

C:/docs/dir1/full094382.db
C:/docs/dir1/full483292.db
C:/docs/dir2/full482952.db
C:/docs/dir2/full930284.db
..
..
..

In the above example, I need only need filename from dir1 and dir2 that was
last modified. Is there a way to do this filtration in the find( sub {} )
above?

Any help will be deeply appreciated.

Thanks,

Rajesh Dorairajan
rajesh.dorairajan@tumbleweed.com

John W. Krahn

2004-03-26, 11:15 pm

Rajesh Dorairajan wrote:
>
> Hello All,


Hello,

> I went through all the documentation and previous mail posts about
> File::Find and finally decided I needed some help.
>
> I've a directory structure I need to parse. The directory contains
> subdirectories with filenames such as
>
> full094382.db
> full483292.db
>
> Now, I need to parse through each subdirectory and pick up the name of the
> file that was MODIFIED MOST RECENTLY. I do have a sort of a code to start
> with.
>
> use strict;
> use warnings;
>
> $\ = "\n";
>
> use File::Find;
>
> my $localdir = 'C:/docs';
> my @files;
>
> find(
> sub { push ( @fullcrls, $File::Find::name ) if /^(full)\w*(\.db)$/ },
> $localdir );
>
> foreach ( @fullcrls ) {
> print;
> }
>
> However, I am not able to figure how to filter out the repeat entries in a
> sub-directory such as
>
> C:/docs/dir1/full094382.db
> C:/docs/dir1/full483292.db
> C:/docs/dir2/full482952.db
> C:/docs/dir2/full930284.db
>
> In the above example, I need only need filename from dir1 and dir2 that was
> last modified. Is there a way to do this filtration in the find( sub {} )
> above?


This should do what you want:

use strict;
use warnings;
use File::Find;
use vars qw( $dir $name );
*dir = *File::Find::dir;
*name = *File::Find::name;

my $localdir = 'C:/docs';
my %files;

find(
sub {
return unless -f;
( not exists $files{ $dir } or $files{ $dir }{ mtime } > -M _ )
and ( @{ $files{ $dir } }{ qw/name mtime/ } = ( $name, -M _ ) )
}, $localdir
);

for my $entry ( values %files ) {
print $entry->{ name }, "\n";
}

__END__



John
--
use Perl;
program
fulfillment
Rajesh Dorairajan

2004-03-29, 3:33 pm

John,

Thanks for the script. I need to filter the result by a specific file
extension, how do I that? I tried,

( not exists $files{ $dir } or $files{ $dir }{ mtime } > -M _ )
and ( @{ $files{ $dir } }{ qw/name mtime/ } = ( $name, -M _ ) )
and ( /^(full)\w*(\.db)$/ )

It does not seem to work. Actually I would be grateful if you could also
help me understand how the script works. I cannot figure out the what role _
plays. I know -M is "Script start time minus file modification time, in
days".

Thanks

Rajesh

> -----Original Message-----
> From: John W. Krahn [mailto:krahnj@acm.org]
> Sent: Friday, March 26, 2004 1:24 AM
> To: beginners@perl.org
> Subject: Re: Search for a file pattern in a directory tree recursively
>
>
> Rajesh Dorairajan wrote:
>
> Hello,
>
> the name of the
> code to start
> /^(full)\w*(\.db)$/ },
> repeat entries in a
> and dir2 that was
> find( sub {} )
>
> This should do what you want:
>
> use strict;
> use warnings;
> use File::Find;
> use vars qw( $dir $name );
> *dir = *File::Find::dir;
> *name = *File::Find::name;
>
> my $localdir = 'C:/docs';
> my %files;
>
> find(
> sub {
> return unless -f;
> ( not exists $files{ $dir } or $files{ $dir }{ mtime } > -M _ )
> and ( @{ $files{ $dir } }{ qw/name mtime/ } = ( $name, -M _ ) )
> }, $localdir
> );
>
> for my $entry ( values %files ) {
> print $entry->{ name }, "\n";
> }
>
> __END__
>
>
>
> John
> --
> use Perl;
> program
> fulfillment
>
> --
> To unsubscribe, e-mail: beginners-unsubscribe@perl.org
> For additional commands, e-mail: beginners-help@perl.org
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
>
>
>


John W. Krahn

2004-03-29, 6:42 pm

Rajesh Dorairajan wrote:
>
> From: John W. Krahn [mailto:krahnj@acm.org]
>
> Thanks for the script. I need to filter the result by a specific file
> extension, how do I that? I tried,
>
> ( not exists $files{ $dir } or $files{ $dir }{ mtime } > -M _ )
> and ( @{ $files{ $dir } }{ qw/name mtime/ } = ( $name, -M _ ) )
> and ( /^(full)\w*(\.db)$/ )


Just substitute:

return unless -f;

With:

return unless /^full\w*\.db$/;


> It does not seem to work. Actually I would be grateful if you could also
> help me understand how the script works. I cannot figure out the what role _
> plays. I know -M is "Script start time minus file modification time, in
> days".


_ is a special file handle that works with the file test operators.

perldoc -f -X
[snip]
If any of the file tests (or either the `stat' or
`lstat' operators) are given the special
filehandle consisting of a solitary underline,
then the stat structure of the previous file test
(or stat operator) is used, saving a system call.
(This doesn't work with `-t', and you need to
remember that lstat() and `-l' will leave values
in the stat structure for the symbolic link, not
the real file.) Example:

print "Can do.\n" if -r $a || -w _ || -x _;

stat($filename);
print "Readable\n" if -r _;
print "Writable\n" if -w _;
print "Executable\n" if -x _;
print "Setuid\n" if -u _;
print "Setgid\n" if -g _;
print "Sticky\n" if -k _;
print "Text\n" if -T _;
print "Binary\n" if -B _;



John
--
use Perl;
program
fulfillment
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com