Home: Perl Programming Help: Win32 Programming Help:
Using file find to search directories problem



RockE70
Novice

Oct 18, 2013, 4:31 AM


Views: 34996
Using file find to search directories problem

Hi Gurus

Could someone point me in the right direction with what I'm trying to do here.

I want to list all directories from a source directory but only drill down to a directory starting with I, D or P and having only 8 characters in the directory name.

The last script in this code (4 variations in total) which I've commented out works but shows all directories from the source directory


Code
use strict; 
use warnings;
use File::Find;
use Fcntl;

#*****************Global Variables**********************
our $wellpath = 'N:\\repos\\open\\Wells\\Regulated';
our $surveypath = 'N:\\repos\\open\\Surveys\\Regulated';
#*******************************************************

Code
#find(sub{print "$_\n";},"$wellpath");



Code
#find(\&dir_names, "$wellpath"); 
# sub dir_names {
# if(-f $File::Find::dir,'/') {
# if (-d $wellpath =~ qr{^([IPD]\d{8})$}) {
# print "$File::Find::dir\n"
# }
# }
# }


Code
find(\&dir_names, "$wellpath"); 
sub dir_names {
if(-f $File::Find::dir,'/' =~ qr{^([IPD]\d{8})$}) {
print "$File::Find::dir\n"
}
}


Code
#find(\&dir_names, "$wellpath"); 
# sub dir_names {
# print "$File::Find::dir\n" if(-f #$File::Find::dir,'/');
# }
#}


Thanks


FishMonger
Veteran / Moderator

Oct 18, 2013, 6:45 AM


Views: 34991
Re: [RockE70] Using file find to search directories problem

Why are you declaring global vars instead of the more appropriate lexical vars?


Code
find(\&dir_names, "$wellpath");

Why are you putting quotes around the var?


Code
if(-f $File::Find::dir,'/' =~ qr{^([IPD]\d{8})$}) {

Why are you doing a -f file test on a directory?

Why are you using the comma to separate the 2 conditions and why are you binding the regex to the '/' directory?

I ask these questions to find out if you understand what the statements are doing.


FishMonger
Veteran / Moderator

Oct 18, 2013, 7:55 AM


Views: 34988
Re: [RockE70] Using file find to search directories problem

See if this does what you want.

Code
find(\&dir_names, $wellpath); 

sub dir_names {

# skip over everything that is not a directory
return if ! -d $File::Find::name;

# skip over directories that don't match required pattern
return if $File::Find::dir !~ qr{^([IPD]\d{8})$};

print "$File::Find::dir\n";
}


You may want to take a look at File::Find::Rule.
http://search.cpan.org/~rclamp/File-Find-Rule-0.33/lib/File/Find/Rule.pm


2teez
Novice

Oct 19, 2013, 8:58 AM


Views: 34973
Re: [RockE70] Using file find to search directories problem

Hi,
FishMonger has given an accurate answer that address the issue you are having. However, I want to point out that, your global variables should still be declared with "my" not "our". i.e

Code
 
#*****************Global Variables**********************
my $wellpath = 'N:\\repos\\open\\Wells\\Regulated';
my $surveypath = 'N:\\repos\\open\\Surveys\\Regulated';
#*******************************************************



FishMonger
Veteran / Moderator

Oct 19, 2013, 11:42 AM


Views: 34967
Re: [2teez] Using file find to search directories problem

That's what I was referring to in my 1st question.

In addition to using the 'my' keyword, the path values need a slight correction. Since single quotes are being used, there is no need to escape the backslashes.


Code
#**************** File Scope Variables *********************   
my $wellpath = 'N:\repos\open\Wells\Regulated';
my $surveypath = 'N:\repos\open\Surveys\Regulated';
#*******************************************************


Personally, I prefer to use forward slashes so that I don't need to worry about the escapes when I use double quotes'


Code
#**************** File Scope Variables *********************   
my $wellpath = 'N:/repos/open/Wells/Regulated';
my $surveypath = 'N:/repos/open/Surveys/Regulated';
#*******************************************************



2teez
Novice

Oct 19, 2013, 1:16 PM


Views: 34960
Re: [FishMonger] Using file find to search directories problem

Hi FishMonger,
About single quote, you are right. Since, the OP was not using a double quote there is not need for escaping the backslash (\) as though it would be interpolated in the single quote.

I think that should also be pointed out. Nice catch!


RockE70
Novice

Oct 20, 2013, 5:33 AM


Views: 34944
Re: [RockE70] Using file find to search directories problem

Thanks for the pointers and thanks for the code example Fishmonger, I'll give a try and see how it goes.

And thanks 2teez for your comments.

The original code I found was on another site and I just tried to get it to work for my problem.


Quote
I ask these questions to find out if you understand what the statements are doing.


The answer is no - I looked at the file::find page and found it terribly verbose but with no great examples about what I was after.


Code
print "$File::Find::dir\n" if(-f #$File::Find::dir,'/');


Not knowing how file::find works the code above I thought just told the module to read through a directory a "file" at a time and then if it finds a directory print it.

My next step is to look for duplicate directories.

Cheers


RockE70
Novice

Oct 20, 2013, 3:44 PM


Views: 34932
Re: [FishMonger] Using file find to search directories problem


In Reply To
See if this does what you want.

Code
 find(\&dir_names, $wellpath);  

sub dir_names {

# skip over everything that is not a directory
return if ! -d $File::Find::name;

# skip over directories that don't match required pattern
return if $File::Find::dir !~ qr{^([IPD]\d{8})$};

print "$File::Find::dir\n";
}


You may want to take a look at File::Find::Rule.
http://search.cpan.org/~rclamp/File-Find-Rule-0.33/lib/File/Find/Rule.pm


Doesn't seem to work Fishmonger, no errors as such but it just sits there like its in an endless loop.

The type of directory structure is like this

N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188/LWD
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188/LWD
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188/LWD
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188/LWD/Final_Logs

It should just show the P00# directory only N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188


RockE70
Novice

Oct 20, 2013, 5:55 PM


Views: 34923
Re: [RockE70] Using file find to search directories problem

ok I got it to work but I have a weird problem that it is now showing multiple instances of the directory depending on how many sub-directories it has.. so if the directory has 3 sub directories it lists the root directory 3 times.


Code
find(\&dir_names, $wellpath);  

sub dir_names {

# skip over everything that is not a directory
return '' if ! -d $File::Find::name;

# skip over directories that don't match required pattern
return if (not $File::Find::dir =~ qr{([IPD]\d{8}$)});

print "$File::Find::dir\n";
}


3 sub directories under P00436188
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188
N:/repos/open/Wells/Regulated/AC/Abalone_1_ENO5655/Logs_digital/P00436188