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

I'm definitely just beginning to get my head wrapped around perl, but I'm finally grasping many things that have eluded me until now. That said...I've managed to hack out a script that *almost* does what I want it to do.

#!/usr/local/bin/perl -w opendir(DIR,".") || die "couldn't open the directory!"; @files = readdir(DIR); closedir(DIR); print 'There are ',scalar(@files)," files in the directory.\n"; foreach $file (@files) { print "Stored on the server as: $file\n"; print "--------------------------------------------\n"; open (CURRENT, "$file") || die "couldn't open the file!"; while ($fileguts = <CURRENT>) { print " $fileguts"; } print "\n\n\n"; close(CURRENT); }

I'm running this in a directory of text files. As you can see, the result of this is how many files are in the directory and the contents of each file separated with a dashed line printed to screen. What I'd *like* to do is only have files that have filenames ending with *.dat to be involved.

I'm not sure if I'm on the right track or if there's a far better way to go about this.
A key concern: this'll need to work on both an NT box and a unix machine.

Any input is greatly appreciated.

Replies are listed 'Best First'.
Re: filtering file names to be added to an array...maybe.
by runrig (Abbot) on Jun 06, 2001 at 09:05 UTC
    One answer is to change your readdir line to this:
    my @files = grep /\.dat$/, readdir DIR;
    Another answer is to use glob'ing:
    while (<*.dat>) { my $file = $_; open(...etc.,etc.); ... } }
Re: filtering file names to be added to an array...maybe.
by myocom (Deacon) on Jun 06, 2001 at 09:06 UTC

    You're on the right track. Rather than using the readdir bit, try using glob, as follows:

    my @files = glob('*.dat');

    Excellent job with the -w on the #! line! You should also add use strict; just under that. This will force you to declare your variables, among other things, so that's why my code snippet above uses my.

    Chatterbox-inspired clarification: You can feed glob a path as part of its argument, like my @files = glob('/temp/*.dat'); Otherwise, glob acts on the current working directory.

      Doesn't glob use the system shell to grab a file list? The OP mentioned that the script needs to run on both NT and *nix. I'm not sure that it would cause any problems in this case, but it could be a potential portability issue.

      ----
      Coyote

        Up to perl5.005_03, glob in Perl spawned a shell. However, as of 5.6.0, glob is implemented using the File::Glob extension (offsite link), which doesn't spawn a shell, and provides configuration options besides.

        As the docs say, it globs like /usr/sh would. And I tested this sort of glob on Win32 and it worked just fine.

        Update: Excellent point, Coyote.

        If the C shell exists then Perl will use it to do filename globbing. The benefit of using the C shell is that it properly handles filenames with spaces in them, whereas some other shells do not.
Re: filtering file names to be added to an array...maybe.
by fs (Monk) on Jun 06, 2001 at 09:31 UTC
    Another way to do it is to skip each file entry unless it matches, ie
    foreach $file (@files){ next unless $file =~ /\.dat$/; # other stuff here... }
Re: filtering file names to be added to an array...maybe.
by larsen (Parson) on Jun 06, 2001 at 14:04 UTC
    Once I had a similar problem, and I came up with this solution (which let you specify an array of files that have to be excluded).

    foreac (@{$param{'-exclude'}}) { $has_to_be_excluded{ $_ }++; } find( sub {push @files, $File::Find::name}, $param{'-directory'} ); @files = grep { !$has_to_be_excluded{ $_ }; /\.html$/; } @files;
Re: filtering file names to be added to an array...maybe.
by Coyote (Deacon) on Jun 06, 2001 at 09:21 UTC
    Change the line

    @files = readdir(DIR);

    to

    my @files = grep( /\.dat$/, readdir(DIR));

    grep in this case will return all the elements of the list returned by readdir that end with a ".dat".

    BTW:Athough this has nothing to do with your question, I would recommend always adding use strict; to the top of your scripts. strict will catch a lot of tricky errors.

    ----
    Coyote

Re: filtering file names to be added to an array...maybe.
by nysus (Parson) on Jun 06, 2001 at 09:04 UTC
    I don't know anything about getting it to work on an NT box. But as far as selecting only certain file extentions, check out my recent question here which might offer you some guidance.

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar";
    $nysus = $PM . $MCF;