Lexicon has asked for the wisdom of the Perl Monks concerning the following question:

I have a bunch of files in a directory which I need to read and play with. However, I don't know what the filenames are, only that they will match a certain format:

example<float number>.txt

For examples, my current files are:
example1.txt example2.txt example3.3.txt
I'm using the code below which seems to work just fine, but is there a better way?

open (DIR, $somedir); while ($_ = readdir DIR) { print "$_\n"; if (/^example([\d\.]+).txt$/) { print " -- FOUND example" . $1 . ".txt\n"; } }

Thanks!

-Lexicon

Replies are listed 'Best First'.
(tye)Re: Reading specific files from a directory
by tye (Sage) on Mar 12, 2001 at 08:46 UTC

    First stab:

    for my $file (  glob( "$somedir/example*.txt" )  ) {

    But if you also have files like "examplebroken.txt", then you'll find too many. So you can refine that. I'll assume you have things like "example3.3.1.2.txt" but not "example-2.45e11.txt":

    for my $file ( grep m#/example(\d+\.)+txt$#, glob( "$somedir/example*.txt" ) ) {

    But I'd stick with your code if you are on an old version of Perl where glob is the sucking death (that is, where it calls /bin/csh to do its work).

    If you are using leading-edge Perl, then you can use File::Spec instead of blithely pasting $somedir and exmample*.txt together with a "/".

            - tye (but my friends call me "Tye")
(sacked) Re: Reading specific files from a directory
by sacked (Hermit) on Mar 12, 2001 at 08:45 UTC
    You can check the filename with a grep:
    opendir(DIR, $somedir) or die "can't open $somedir for read: $!\n"; @files_i_want = grep { /^example\d(?:\.\d)*\.txt$/ } readdir DIR; closedir(DIR) or die "error closing $somedir: $!\n";
    Then use @files_i_want as desired.

    --sacked
Re: Reading specific files from a directory
by AgentM (Curate) on Mar 12, 2001 at 08:45 UTC
      Is there a way to get back what that * was equal to? This looks nice and tidy and convenient, but I'll need the * for later, so I was just wondering.

      Update - Oh. <example*.txt> returns the filenames which map it, not the text of the files themselves. Something just didn't click the first time I read this.

      -Lexicon

Re: Reading specific files from a directory
by Tuna (Friar) on Mar 12, 2001 at 08:44 UTC
    you could use:
    #!/usr/bin/perl -w use strict; my $somedir = "/home/me/lala"; my $file; opendir (DIR, $somedir); while ($file = readdir DIR) { print "$file\n"; if ($file =~ /^example\.\d+\.txt$/) { print " -- FOUND example: $file\n"; } }
    I'm not whether my code is any faster or more optimal than yours; I'll leave that for monks greater than I =) BTW, I'm not sure if it's a typo but:
    open (DIR, $somedir);
    should be:
    opendir (DIR, $somedir);
      Somedays it just doesn't pay to post code (it almost always pays to write code thankfully.) Yeah, the opendir is a typo here that I made while simplifying the problem down for PM. And uh....I have no excuse for why I regenerated my file name. In a hurry combining code and not thinking hard enough. I'm gonna go back to my cave and write HTML now.

      -Lexicon

Re: Reading specific files from a directory
by Anonymous Monk on Mar 13, 2001 at 02:46 UTC
    File glob'it, and watch newbies cower in AWE!
    
    my @dirc = <*>;
    foreach $dir (@dirc) {
       print "$dir\n";
       print "  -- Found $dir\n"
          if $dir =~ /example(\d*?)\.txt/;
    }
    
    Only one line shorter, but I do think is more efficient.
Re: Reading specific files from a directory
by Anonymous Monk on Mar 13, 2001 at 03:00 UTC
    If you are on unix, you can findout like this in single line :
    ls -l |perl -ne 'print if /example\d+\.txt/
    Ashok
Re: Reading specific files from a directory
by scain (Curate) on Mar 13, 2001 at 21:13 UTC
    I just wanted to comment on using glob as some monks have proposed.

    Generally, it works fine, but be careful if there are many (>1000) files in the directory as it can be slow. If there are, it would probably be better to user readdir and grep. -Scott

      Modern versions of Perl implement glob using readdir and grep or even faster equivalents written in C and compiled into the perl executable. For older versions of Perl, glob is the sucking death and should be avoided at almost any cost.

              - tye (but my friends call me "Tye")
        What counts as "older versions of perl"? I am using 5.005(+/-) and when working with lots of files (sometimes more than 20,000), glob just doesn't work.

        Thanks for pointing this out though, as it indicates that it may be time for me to move on (to a newer version, that is).

        --Scott