views:

136

answers:

4

In Perl, you can get a list of files that match a pattern:

my @list = <*.txt>;
print  "@list";

Now, I'd like to pass the pattern as a variable (because it's passed into a function). But that doesn't work:

sub ProcessFiles {
  my ($pattern) = @_;
  my @list = <$pattern>;
  print  "@list";
}

readline() on unopened filehandle at ...

Any suggestions?

A: 

What about wrapping it with an "eval" command? Like this...

sub ProcessFiles {
  my ($pattern) = @_;
  my @list;
  eval "\@list = <$pattern>";
  print @list;
}
Robert Wohlfarth
Never, ever, ever, ever do this. The `glob` operator is the correct answer.
friedo
You're right, glob is a much better answer. Thanks for the correction. Why "never, ever, ever, ever" do this?
Robert Wohlfarth
Robert, you should avoid string `eval` whenever possible; who knows what nefarious data might end up in `$pattern`, especially if that is derived from user input. Even if not malicious, weird stuff finding its way into an `eval` can be the cause of many painful bugs.
friedo
A: 

Why not pass the array reference of the list of files to the function?

my @list = <*.txt>;
ProcessFiles(\@list);

sub ProcessFiles {
    my $list_ref = shift;
    for my $file ( @{$list_ref} ) {
        print "$file\n";
    }
}
Alan Haggai Alavi
I knew someone would suggest this. The problem is that it's actually a variable to begin with, like this: `my $pattern = "test-%d-*.txt"; ProcessFiles(sprintf($pattern, "51"));`
+7  A: 

Use glob:

use strict;
use warnings;

ProcessFiles('*.txt');

sub ProcessFiles { 
  my ($pattern) = @_; 
  my @list = glob $pattern;
  print  "@list"; 
} 

Here is an explanation for why you get the warning, from I/O Operators:

If what the angle brackets contain is a simple scalar variable (e.g., $foo), then that variable contains the name of the filehandle to input from... it's considered cleaner to call the internal function directly as glob($foo), which is probably the right way to have done it in the first place.)

toolic
A: 
use File::Basename;
@ext=(".jpg",".png",".others");
while(<*>){
 my(undef, undef, $ftype) = fileparse($_, qr/\.[^.]*/);
 if (grep {$_ eq $ftype} @ext) {
  print "Element '$ftype' found! : $_\n" ;
 }
}
ghostdog74