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

Apologies if this has been asked a lot. I tried several different searches but I don't think I'm searching the right terms.

I have a directory of log files without file extensions that I want to read data from. The directory consists of files starting with "R" and "D", I only want to read the files starting with "R" but am having trouble figuring out how. I am also having problems opening the files if they do not have a file extension. Here is what I have so far.

opendir( DIR, $directory ) || die "Unable to open directory - $!\n"; my @files = grep /\.txt/, readdir( DIR ); closedir( DIR );

I tried replacing the /\.txt/ with /\./ but I get an access denied message.

To deal with the files starting with "R" I have tried using variations on glob, and =~R but it's not working. Thanks for any help and keep in mind that I'm new so please explain code that may be confusing to a rookie.

Replies are listed 'Best First'.
Re: Reading specific files
by GrandFather (Saint) on Sep 21, 2009 at 23:24 UTC

    You say that the files of interest don't have an extension, but your grep is matching only files with the extension .txt. The first step is to change your grep to:

    my @files = grep /^R/, readdir( DIR );

    to match files that start with R. The ^ matches the start of the string thus the R requires that the first character be R. When you have the correct list of files the open should be trivial, but remember that the names returned by readdir don't include the directory path so, if the files are not in the current working directory, you will need to prefix $directory to the file names in the open. Probably something like:

    for my $filename (@files) { open my $inFile, '<', "$directory/$filename" or die "Can't open $d +irectory/$filename: $!"; ... close $inFile; }

    True laziness is hard work
      your grep is matching only files with the extension .txt

      molson is using the regular expression  /\.txt/ which will match the string '.txt' anywhere in $_ while a file extention implies that the string will only appear at the end of the string in $_.

      Sorry about that, I should have clarified that the only way I was able to get my code to work was add the .txt extension to some files.

      the grep /^R/ works great! Thank you!!

Re: Reading specific files
by toolic (Bishop) on Sep 21, 2009 at 23:25 UTC
    This will give you a list of the files which begin with "R":
    my @files = grep { (-f $_) and (/^R/) } readdir( DIR );

    Keep in mind that readdir also returns subdirectories, hence the -f file check. You then need to open files individually.

Re: Reading specific files
by cdarke (Prior) on Sep 22, 2009 at 08:24 UTC
    To deal with the files starting with "R" I have tried using variations on glob
    my @files = glob("$directory/R*");
    No need for a regular expression. You might have to use File::Glob 'glob'; if files or directories in your pattern have imbedded whitespace.
Re: Reading specific files
by raisputin (Scribe) on Sep 21, 2009 at 23:32 UTC
    #!/usr/bin/perl -w opendir(DIR, "."); @files = grep(/^R/,readdir(DIR)); closedir(DIR); foreach $file (@files) { print "$file\n"; }
    That works. Stolen from:
    Here

      Don't steal. Stolen goods often have nasty baggage. In this case strict is missing, there is no error checking on the opendir, package variables rather than lexical variables are being used and the various open issues that may face the OP are not addressed. A better version of the code is:

      use strict; use warnings; opendir my $scanDir, $directory or die "Unable to open directory $dire +ctory: $!\n" my @files = grep /^R/, readdir $scanDir; closedir $scanDir; for my $filename (@files) { open my $inFile, '<', "$directory/$filename" or die "Can't open $d +irectory/$filename: $!"; ... close $inFile; }

      True laziness is hard work
        Fair enough, I just assumed (ya, I know) the OP would use strict as that is standard practice... As for the rest, it was just cut-n-paste but it worked. I was tempted to just say change it to /^R/ but whatever. Live and learn :)