File::Find gives me current dir (.)?

B

ben.rogers

I wrote a subroutine that finds all of the files of a certain type.
For example, if I want to find all .fm and .book files, I push these
file types to @file_types and send that to File::Find or to grep to get
my list of files (depending on whether the search should be recursive.

I print that list as shown below. Note that I get:

Open
Convert mif
Close

I haven't been able to get rid of this. Am I getting the current dir
(.) or something?

thanks for any advice,

b



################################# FIND FILES
# Print instructions for finding files to the script created by
createScriptFile.
# Get the input directory ($inputdir) and recursion setting ($recursion
= 1 or 0).
# Get the file types (@file_types) and make a string used by grep or
File::Find.
sub fileFinder {
my $file_match_string = join ("|", @file_types);
if ($recursive =~ 1) {
chdir "$inputdir";
find (\\&wanted, "$inputdir");
sub wanted(){
if (\$File::Find::name =~ /($file_match_string)\$/i && -f){
print STDOUT "FOUND: \$File::Find::name\\n";
push \@files, \$File::Find::name;
}
}
print STDOUT "Finished finding files.";
} else { # Just GREP and don't use recursion.
print "my \@files = '';\n";
print "opendir(DIR, \"$inputdir\");\n";
print "\@files = grep /$file_match_string/,";
print "readdir(DIR);\nclosedir(DIR);\n";
}
}


--------------- printed list of files -------------------------
Open
Convert mif
Close

Open C:\Adobe\mifaliscious\b4\deploying_projects.fm
Convert mif C:\Adobe\mifaliscious\b4\deploying_projects.fm
Close C:\Adobe\mifaliscious\b4\deploying_projects.fm

Open C:\Adobe\mifaliscious\b4\front.fm
Convert mif C:\Adobe\mifaliscious\b4\front.fm
Close C:\Adobe\mifaliscious\b4\front.fm

Open C:\Adobe\mifaliscious\b4\server.book
Convert mif C:\Adobe\mifaliscious\b4\server.book
Close C:\Adobe\mifaliscious\b4\server.book

Open C:\Adobe\mifaliscious\b4\serverIX.fm
Convert mif C:\Adobe\mifaliscious\b4\serverIX.fm
Close C:\Adobe\mifaliscious\b4\serverIX.fm
 
J

Jim Keenan

I wrote a subroutine that finds all of the files of a certain type.

################################# FIND FILES
# Print instructions for finding files to the script created by
createScriptFile.
# Get the input directory ($inputdir) and recursion setting ($recursion
= 1 or 0).
# Get the file types (@file_types) and make a string used by grep or
File::Find.
sub fileFinder {
my $file_match_string = join ("|", @file_types);
if ($recursive =~ 1) {

Wrong Perl syntax. =~ is the binding operator used in testing strings
with regular expressions. You probably want:

if ($recursive == 1) { ...

See: perldoc perlop

But since you're only permitting $recursive to be either '1' or '0', you
can more simply say:

if ($recursive) { ...
chdir "$inputdir";
find (\\&wanted, "$inputdir");
sub wanted(){
if (\$File::Find::name =~ /($file_match_string)\$/i && -f){
print STDOUT "FOUND: \$File::Find::name\\n";
push \@files, \$File::Find::name;

Wrong, wrong! What your code says is "Push a reference to a scalar onto
a reference to an array" ... which doesn't work.

You probably want:

push @files, $File::Find::name;

Read the docs:

perldoc -f push


But the fact that you're putting your call to File::Find inside another
subroutine suggests to me that you don't really understand how to use
it. (Granted, its syntax is not the easiest to grok at first.) But
once you've corrected the mistakes above, try rewriting your program
without sub FileFinder and without any of the code below this point.
}
}
print STDOUT "Finished finding files.";
} else { # Just GREP and don't use recursion.
print "my \@files = '';\n";
print "opendir(DIR, \"$inputdir\");\n";
print "\@files = grep /$file_match_string/,";
print "readdir(DIR);\nclosedir(DIR);\n";
}
}
Jim Keenan
 
T

Tad McClellan

[ something horrid has happened to the formatting of your code...]

if ($recursive =~ 1) {


if ($recursive =~ /1/) { # contains a "1" character
or
if ($recursive eq '1') { # equals the "1" chararacter
or
if ($recursive == 1 ) { # equals the number 1

depending on whichever it is that you were really trying to get there.

chdir "$inputdir";


You should not use useless quotes.

You should check the return value to see if you actually
got what you asked for:

chdir $inputdir or die "could not cd to '$inputdir' $!";

find (\\&wanted, "$inputdir");
^
^ why the extra backslash?

sub wanted(){
^^
^^ why the prototype?

if (\$File::Find::name =~ /($file_match_string)\$/i && -f){
^ ^
^ ^
^ why the extra backslashes?


print STDOUT "FOUND: \$File::Find::name\\n";
^
^ why the extra backslash?
push \@files, \$File::Find::name;
^ ^
^ ^
^ why the extra backslashes?


print "my \@files = '';\n";
print "opendir(DIR, \"$inputdir\");\n";
print "\@files = grep /$file_match_string/,";
print "readdir(DIR);\nclosedir(DIR);\n";


Why are you print()ing code?

Is this a program-writing program that you are working on?
 
B

ben.rogers

I made a mistake in my original post and Tad managed to get through the
garbage to figure it out. Yes, I am writing a program-writing program.
The code example was originally in a HERE block and I did a poor job of
making it working code (instead of code-writing code) before asking for
help.

Anyway, it took the ($recursive) suggestion and switched to glob to
simplify non-recursive searching. I now have this (it works):

#!C:\\Perl -w
use File::Find;

$recursive = 0;

if ($recursive){
find (\&wanted, "C:/Adobe/mifaliscious/b4");
sub wanted(){
if ($File::Find::name =~ /(.fm)$/i && -f){
print STDOUT "FOUND: $File::Find::name\n";
push @files, $File::Find::name;
}
}
} else {
chdir "C:/Adobe/mifaliscious/b4";
@files = glob "*.fm";
foreach (@files) {print STDOUT "FOUND: $_\n";}
}


I can't see how to make it simpler or more elegant, but if there is a
way please let me know. Your responses made me analyze things more
carefully and I appreciate the help. Hope I got it right! works anyway.
b
 
T

Tad McClellan

#!C:\\Perl -w
use File::Find;


You need a

use strict;

there.

And

use warnings;

is better than -w.

if ($File::Find::name =~ /(.fm)$/i && -f){


Since it is anchored to the end anyway, you don't need the
other parts of the path, you can just use $_.

You shouldn't capture when you're not going to use the captured chars.

That will match a file named "foofm" you know...

Fixing all of that, we end up with:

if ( /\.fm$/i and -f ) {


chdir "C:/Adobe/mifaliscious/b4";


You should check the return value to see if you got what you asked for:

chdir "C:/Adobe/mifaliscious/b4" or
die "could not cd to 'C:/Adobe/mifaliscious/b4' $!";

foreach (@files) {print STDOUT "FOUND: $_\n";}


You can eliminate some punctuation:

print STDOUT "FOUND: $_\n" foreach @files;
 
T

Tad McClellan

I made a mistake in my original post and Tad managed to get through the
garbage to figure it out. Yes, I am writing a program-writing program.
The code example was originally in a HERE block


A here document is not a "block", it is a "string".

If you single-quote the here-doc token, then you wouldn't have
to do all that backslashing of dollar signs and whatnot.
 
B

ben.rogers

Of course, all of this advice is good and it all work. Thanks, I
learned alot.

b
 
J

John W. Krahn

I made a mistake in my original post and Tad managed to get through the
garbage to figure it out. Yes, I am writing a program-writing program.
The code example was originally in a HERE block and I did a poor job of
making it working code (instead of code-writing code) before asking for
help.

Anyway, it took the ($recursive) suggestion and switched to glob to
simplify non-recursive searching. I now have this (it works):

#!C:\\Perl -w
use File::Find;

$recursive = 0;

if ($recursive){
find (\&wanted, "C:/Adobe/mifaliscious/b4");
sub wanted(){
if ($File::Find::name =~ /(.fm)$/i && -f){
print STDOUT "FOUND: $File::Find::name\n";
push @files, $File::Find::name;
}
}
} else {
chdir "C:/Adobe/mifaliscious/b4";
@files = glob "*.fm";
foreach (@files) {print STDOUT "FOUND: $_\n";}
}


I can't see how to make it simpler or more elegant, but if there is a
way please let me know. Your responses made me analyze things more
carefully and I appreciate the help. Hope I got it right! works anyway.


#!C:\\Perl -w
use File::Find::Rule;

my $dir = 'C:/Adobe/mifaliscious/b4';

my $recursive = 0;

my @files = $recursive
? File::Find::Rule->name( qr/\.fm$/i )->file()->in( $dir )
: glob "$dir/*.fm";

print map "FOUND: $_\n", @files;




John
 
T

Tad McClellan

Bernie Cosell said:
} And
}
} use warnings;
}
} is better than -w.

I thought they were the same... what's the difference??


-w is global, use warnings is lexical (scoped).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top