http://www.perlmonks.org?node_id=293241

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

Hello Monks,

I have two questions that I'm seeking guidance with:

1. Is there a way so I do not have to write out each file seprately? For example something like:
my @files = ('d:\log\exported\10Sep2003.elog' .. 'd:\log\exported\17Sep2003.elog')
I know this will not work, but I think you guys will see what I'm trying to do.

2. In the below code, my 'for' loop is not working the way I intended to. It is combining all of the file names into one file and then trying to proceed with the while loop. Here is the error I get when I run this script:
Can not open d:\log\exported\10Sep2003.elog d:\log\exported\11Se p2003.elog d:\log\exported\12Sep2003.elog d:\log\exported\13Sep2 003.elog d:\log\exported\14Sep2003.elog d:\log\exported\15Sep200 3.elog d:\log\exported\16Sep2003.elog d:\log\exported\17Sep2003. elog d:\log\exported\22Sep2003.elog: No such file or director
I thought that it would iterate over the first file move onto the while loop and then begin again. Anyone know what I'm doing wrong?
My Script: use warnings; use strict; my $file1 = 'd:\log\exported\10Sep2003.elog'; my $file2 = 'd:\log\exported\11Sep2003.elog'; my $file3 = 'd:\log\exported\12Sep2003.elog'; my $file4 = 'd:\log\exported\13Sep2003.elog'; my $file5 = 'd:\log\exported\14Sep2003.elog'; my $file6 = 'd:\log\exported\15Sep2003.elog'; my $file7 = 'd:\log\exported\16Sep2003.elog'; my $file8 = 'd:\log\exported\17Sep2003.elog'; my $file9 = 'd:\log\exported\22Sep2003.elog'; my @files = qq($file1 $file2 $file3 $file4 $file5 $file6 $file7 $file8 $file9); my ($fw, $rule1, $dst); for (@files){ open (FILE, $_) or die "Can not open $_: $!\n"; while (<FILE>){ ($fw, $dst, $rule1) = (split /;/)[3,11,15]; print if ($fw =~ /192\.168\.15\.1/) && ($dst =! /192\.168\.31\.25/) && ($rule1 =~ /\b12\b/); }

Replies are listed 'Best First'.
Re: Range of File Names and For/While Problem
by jeffa (Bishop) on Sep 22, 2003 at 19:34 UTC
    Take a good look at the contents of @files .. it's just one big ole string. Try this instead:
    my @files = qw( d:\log\exported\10Sep2003.elog d:\log\exported\11Sep2003.elog d:\log\exported\12Sep2003.elog d:\log\exported\13Sep2003.elog d:\log\exported\14Sep2003.elog d:\log\exported\15Sep2003.elog d:\log\exported\16Sep2003.elog d:\log\exported\17Sep2003.elog d:\log\exported\22Sep2003.elog );
    You could, of course, use Perl to create the list for you:
    my @files = map q|d:\log\exported\\| . $_ . 'Sep2003.elog', 10..17,22;
    But you will probably need to pull in a Date module to calculate the edge conditions.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Range of File Names and For/While Problem
by Enlil (Parson) on Sep 22, 2003 at 19:38 UTC
    Question #1: Would something like be what you are looking for:
    my @files; push @files, "d:\\log\\exported\\" . sprintf("%02",$_) . "Sep2003.elog +" for 1 .. 28;
    Note that the sprintf is in there assuming that the numbers are always two digits (e.g. 01, 09,10,etc).

    Question #2: The reason this puts everything together is because of the qq, drop that and add commas between the variables and it should work as expected what you have now is the same as the following code:

    my @files = ("$file1 $file2 $file3 $file4 $file5 $file6 $file7 $file8 +$file9");
    which explains what you are seeing printed.

    update: Added that commas need to be added as well. Also, it would be easier as mentioned above to change qq to qw.

    -enlil

Re: Range of File Names and For/While Problem
by svsingh (Priest) on Sep 22, 2003 at 19:47 UTC
    You may want to try globbing to build your list.
    use File::Glob qw(:globally :nocase); chdir 'd:\log\exported'; my @files = <*.elog>;
    Alternatively, if you want to do processing on each file in the list, File::Find will also work for you and would give you a little more control over which files make it into the list.
      I thought I'd take a quick break from work and see if I could write the File::Find version of this. The following code will create a list of the files modified in the past seven days in d:\log\exported. I didn't backdate the files in my directory to test this thoroughly, but it seems to work.
      use File::Find; my $ageLimit = 7; # the age (in days) of the oldest file you want to +process my $ageCutoff = time - $ageLimit * (60*60*24); # the cutoff time my @logFiles = (); my $findFilter = sub { if ( (stat($_))[9] > $ageCutoff ) { # only push files newer than c +utoff push @logFiles, $_; } return; }; find($findFilter, 'd:\log\exported'); # populates the list

        Dont forget File::Find is recursive. So youll grab all the files that match in sub directories as well, and should it contain a directory thats new enough you'll have a problem as it'll get included as well. Also as you are simply pushing the base name into the list you wont even know whats happening until you start to diagnose missing files and find them two layers deeper in the file structure :-)

        use File::Find; my @files; my $age_limit=7; find { wanted=>sub { -f and -M($_) < $age_limit and push @files, $_ }, no_chdir=>1 }, 'd:\log\exported'; print join("\n",@files),"\n";

        You should take a look at find2perl


        ---
        demerphq

        Everybody remember the Gandhi quote?

          First they ignore you, then they laugh at you, then they fight you, then you win.

        Gentlemen and ladies, this newest leaked memo from Microsoft confirms that we are advancing through GandhiCon Three.