insta.gator has asked for the wisdom of the Perl Monks concerning the following question:

PERL noob here.

I need to load an array with file names produced from a wildcard search on a Windows box. I would like to pass the wildcard to the PERL script if possible. Not having luck. Here is what I have

use Cwd; my $dir = getcwd; opendir DIR, $dir; my @prfiles = grep { $_ eq $ARGV[0] && $_ ne '.' && $_ ne '..' } readd +ir DIR; closedir DIR;

I created using examples that I have found. I think that partially, my problem is with the wildcarding.

This is what I would like to do: "perl testfile*.dat". Assuming I have testfile1,2,3,4.dat in the directory, it would load the array with these file names.

Any help would be greatly appreciated!

Replies are listed 'Best First'.
Re: Loading an array with file names
by Corion (Pope) on May 04, 2015 at 20:28 UTC

    Instead of doing the work yourself, use a module:

    use File::Glob 'bsd_glob'; my @files= bsd_glob $dir; print "$_\n" for @files;
Re: Loading an array with file names
by GotToBTru (Prior) on May 04, 2015 at 21:26 UTC

    * means one thing in filename wildcards and another in regexes. It does work in glob().

    use Cwd; my $dir = getcwd; opendir DIR, $dir; my $filter = shift; $qfilter = quotemeta $filter; $qfilter =~ s/\\\*/.*/; $qfilter = qr($qfilter); my @regfiles = grep { -f ; /$qfilter/ } readdir DIR; seekdir DIR,0; @globfiles = glob($filter); closedir DIR; print "$_\n" for @regfiles; print "\n"; print "$_\n" for globfiles;
    Dum Spiro Spero
Re: Loading an array with file names
by jeffa (Bishop) on May 04, 2015 at 21:01 UTC

    If you are only performing simple, ad hoc tasks then this is one of those great times when you can get away with writing on-the-fly one-liners. Let's say you wanted to do something like rename the files so that spaces are converted into underscores. You can incrementally change the one-liner to ensure you are changing the right things:

    $ touch data/{1..5}\ with\ spaces.dat $ perl -le'for(<data/*.dat>){print}' $ perl -le'for(<data/*.dat>){$o=$_;tr/ /_/;print}' $ perl -le'for(<data/*.dat>){$o=$_;tr/ /_/;rename $o,$_}'

    I realize you are not using Unix, but the only function of the 1st command is to create some files that have spaces in their names. The 2nd command shows you the files you are going to change. The 3rd command shows you what their new names are going to be. The final command does the actual work. I use this kind of technique almost daily.

    If you want to write production code, best to use the built in glob function instead of the <.. > construct. (See Perl::Critic::Policy::BuiltinFunctions::RequireGlobFunction.)


    (the triplet paradiddle with high-hat)
      I use this kind of technique almost daily.

      Heh. Me too. In fact, one of the first things I did when I started using Perl 20 years ago (seems like only yesterday - how time flies!) was to write a script that made this easier, and it quickly grew to do any manner of command-line stuff where I needed any sort of substitution to make an "output" name from an "input" name: shloop -- execute shell command on a list.

      Here's how I eliminate those pesky spaces from file names:

      ls | grep " " | shloop -e rename -s 'tr: :_:'
      (Of course, there's a "-n" option for "no-op", to just print what would happen without actually doing it.)

      It does get tricky when a directory has spaces in its name, and it also contains files with spaces in their names - renaming has to be done just one level at a time.

Re: Loading an array with file names (Path::Tiny File::Find::Rule)
by Anonymous Monk on May 05, 2015 at 00:14 UTC

    Path::Tiny is a very good interface to readedir, very good substitute for glob

    use Path::Tiny qw/ path cwd /; my $dir = cwd(); my( $first ) = @ARGV; # my @prfiles = grep { $_ eq $first } path( $dir )->children; my @prfiles = path('.')->children( qr/\Q$first\E/ );

    File::Find::Rule is the next step up

    use File::Find::Rule qw/ find rule /; my( $first ) = @ARGV; my @prfiles = find(file => name => $first, maxdepth => 1, in => '.');

    '.' is common name for cwd :)

    Now you know :)

Re: Loading an array with file names
by edimusrex (Monk) on May 04, 2015 at 20:40 UTC
    You could do something like this using back ticks to issue a dos command and capture the results in an array
    #!/usr/bin/perl $folder = 'C:'; $input = $ARGV[0]; @array = `dir /b ${folder}\\${input}`; foreach (@array) { print "$_"; }
    You could remove the $folder variable and set it to $ARGV1 to allow the second command line variable to be the path of where you are searching.

    Example *.txt C: would seach the C:\ directory for anything ending in .txt