in reply to Passing file names to search directories

Global symbol "$fnames" requires explicit package

This specific error is because you have an array named @fnames but you later try to dereference an undeclared arrayref named $fnames.

You've also got an issue with the part of your syntax that tries to access the element within the array:

@$fnames->{filename}
That probably would not do what you think even if you didn't have the first problem. You can't access an element of an array, whether directly or via reference, by a key name.

If, as seems possible from the code you posted, you are receiving into your sub listdirs() two arguments, each a reference to an array, you can get what I think you want with:

my $res_files = list_dirs($dir,$datanames); sub list_dirs { my ( $locations, $fnames ) = @_; ... foreach my $href ( @{ $fnames } ) { my $filename = $href{'filename'}; # do something with filename ... } }
Or you could get the list of filenames with something like:
my $res_files = list_dirs($dir,$datanames); sub list_dirs { my ( $locations, $fnames ) = @_; my @filenames = map { $_->{'filename'} } @{ $fnames }; ... }
But, this raises the question of why you have an array of anonymous hashes containing just one key-value pair?

And in general, in Perl, there's usually a tool to do something common like what you want. You might like to use Path::Iterator::Rule:

use Path::Iterator::Rule; ... my $res_files = list_dirs($dir,$datanames); sub list_dirs { my ( $locations, $fnames ) = @_; # assumes each is a simple arrayref my $finder = Path::Iterator::Rule->new; $finder->name( @{ $fnames } ); my $get_next_match = $finder->iter( @{ $locations } ); my @found_filenames; while ( defined ( my $match = $get_next_match->() ) ) { push @found_filenames, $match; } return \@found_filenames; }

See also Yes, even you can use CPAN.

Hope this helps!


The way forward always starts with a minimal test.

Replies are listed 'Best First'.
Re^2: Passing file names to search directories
by Anonymous Monk on Dec 28, 2016 at 20:45 UTC
    Great explanation, but how would I use this line or the array @filenames:
    my @filenames = map { $_->{'filename'} } @{ $fnames };

    in this line:
    find( { wanted => sub { push @files, $_ unless $_ eq '.' || $_ eq '..' + || $_ !~ m/@filenames$/} , no_chdir => 1 }, @dirs);

    That's where I am trying to understand the most, thanks!
      I found that this way, it works:
      my @filenames = map { $_->{'filename'} } @{ $fnames }; my $rx_fnames = join '|', @filenames; find( { wanted => sub { push @files, $_ unless $_ eq '.' || $_ eq '.. +' || $_ !~ m/$rx_fnames$/} , no_chdir => 1 }, @dirs);

      Any feed back is welcome!