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

I am attempting to read a directory to get all files in the directory, pass these file names into a foreach loop. These files are all monthly PS Accounting Report Files, which I need to parse in the foreach loop to determine those that match a particular month. The PS Account Files have the following format:

Jun 1 03:20 2007 MONTHLY USAGE FOR 05/2007 FOR xsd00544 Page 1 LOGIN CPU (MINS) KCORE-MINS CONNECT (MINS) DISK + # OF # OF # DISK FEE UID NAME PRIME NPRIME PRIME NPRIME PRIME NPRIME + BLOCKS PROCS SESS SAMPLES 0 TOTAL 11997 26981 799331072 1899742080 13264 20 +500 0 32403945 226 0 0 0 root 1089 2594 12452976 29521392 0 0 0 11 +588066 0 0 0 1 daemon 0 0 174 423 0 0 0 3293 0 0 + 0 3 sys 1 4 1805 5657 0 0 0 9387 0 0 + 0 4 adm 1 52 546 48639 0 0 0 37050 0 0 + 0 71 lp 0 0 0 12 0 0 0 20 0 0 0 103 ctsccw1 0 0 75 22 35 12 0 164 6 0 + 0 108 scoilg1 0 0 14 0 1720 4070 0 26 6 + 0 0 116 sdbaa12 0 0 140 24 475 838 0 212 12 + 0 0 117 dptid01 0 0 0 0 0 21 0 0 29 0 +0 118 sdbast1 0 0 195 21 0 0 0 94 0 0 + 0 121 sdbaa01 0 0 0 0 5 0 0 0 1 0 0 170 cmredm1 0 0 0 2 0 463 0 3 2 0 +0 223 pimdp01 0 4 152 9135 0 0 0 1780 0 + 0 0 226 sdbasc2 0 0 21 0 140 0 0 39 2 0 + 0 228 mqm 5 19 15007 46540 0 0 0 150133 0 + 0 0 269 pirdp01 3 1 15850 2602 0 0 0 1311 0 + 0 0 284 pptip01 0 16 0 120016 0 0 0 3175 0 + 0 0 317 pomgp01 19 37 78967 285738 0 0 0 178868 + 0 0 0 335 ammdcc1 0 0 7 0 122 0 0 29 1 0 + 0 340 sdbsby1 0 0 1 3 0 109 0 1 1 0 +0 359 pmfwp01 0 0 0 1 0 0 0 1 0 0 0 404 bmw 0 0 5 0 0 0 0 14 0 0 0 405 ccsssl1 0 0 0 3 0 7 0 8 1 0 0 406 scspfw1 0 0 14 0 776 0 0 18 3 0 + 0 409 ccssll1 0 0 0 4 0 132 0 12 1 0 + 0 410 ccsslv1 0 0 18 0 0 0 0 22 0 0 +0 594 pipmp01 591 1151 20229524 42349476 0 0 0 + 6576051 0 0 0 605 pbmwp01 0 3 0 99267 0 0 0 495 0 0 + 0 643 ccssat1 0 0 0 14 0 724 0 20 4 0 + 0 645 ccssjt1 0 0 0 1 0 25 0 9 1 0 0 790 cmrejc1 0 0 4 13 20 738 0 31 9 0 + 0 799 cdigjc1 0 0 15 0 1424 0 0 20 4 0 + 0 817 domsd01 0 0 71 0 24 0 0 20 9 0 + 0 819 cmresp2 0 0 6 29 723 2506 0 47 11 + 0 0 824 cmrehc1 0 0 12 16 266 669 0 42 6 +0 0 942 sdbamg1 0 0 28 0 243 0 0 69 3 0 + 0 958 maestro 335 685 1506022 3072424 0 0 0 2 +066 0 0 0 1001 ndmuser 78 279 242614 918368 0 0 0 707 +430 0 0 0 1003 amssmt2 0 0 18 0 86 0 0 68 2 0 + 0 1005 amsspw1 0 0 0 0 18 0 0 0 1 0 +0 1057 cmrerb1 0 0 5 4 577 40 0 16 5 0 + 0 1128 ccssrs1 0 0 0 2 195 369 0 3 2 0 + 0 1130 ccsswc1 0 0 0 10 0 463 0 12 5 0 + 0 1157 sybprd01 0 0 0 3 0 0 0 3 0 0 +0 1164 s2p1 0 0 6 0 25 0 0 5 1 0 0 1221 scspba1 0 0 5 6 4 12 0 19 2 0 + 0 1280 sybsrd0k 17 63 5824025 13749965 0 0 0 +14779 0 0 0 1356 sdbasn1 0 0 20 4 256 834 0 28 3 +0 0 1360 dimcd01 0 0 20 7 132 8 0 30 4 0 + 0 1451 sybprd0l 1482 3844 12557 2853173 0 0 0 + 103885 0 0 0 1477 sdsmfl1 0 0 4 0 128 0 0 10 1 0 + 0 1496 f2pa 256 580 4356176 10327754 0 0 0 75 + 0 0 0 1508 pdb2admn 0 1 0 5111 0 0 0 1275 0 + 0 0 Jun 1 03:20 2007 MONTHLY USAGE FOR 05/2007 FOR xsd00544 Page 2 1597 scoiyk1 0 0 6 0 15 0 0 8 1 0 +0 1608 ccssro1 0 0 4 0 179 0 0 10 1 0 + 0 2014 ccssjj1 0 0 0 3 0 2 0 10 1 0 +0 2132 s2pe 3277 5178 349899264 649494912 0 0 0 + 6362691 0 0 0 2136 s2pi 1 2 71260 171081 0 0 0 5587 0 + 0 0 2614 s2pv 0 1 10975 30646 0 0 0 1156 0 + 0 0 3916 spmdjg1 0 0 0 474 0 0 0 10 0 0 + 0 4529 sdsmmm1 0 0 20 0 1 0 0 69 5 0 + 0 4774 dctid01 1 0 366960 24 3720 3648 0 1163 + 27 0 0 5112 ccssew1 0 0 6 0 589 35 0 15 2 0 + 0 5141 pctip01 1538 3560 4766369 10024204 0 0 0 + 6351759 0 0 0 6040 oraprd0y 0 0 4 0 0 0 0 3 1 0 +0 6102 pimcp55 0 0 132 0 0 0 0 171 0 0 + 0 6723 oraprd0s 2390 5799 330034080 925707520 0 0 + 0 260013 0 0 0 6874 abmwrb1 0 0 8 0 316 0 0 28 1 0 + 0 7897 ccssjs1 0 0 13 0 350 0 0 32 4 0 + 0 7958 sybmrd04 853 2673 24337680 66644340 0 0 0 + 23963 0 0 0 8120 sussoa1 0 0 5 4 614 1191 0 18 5 +0 0 8358 ccssds1 0 0 0 26 0 70 0 43 9 0 + 0 8359 ccssas1 0 0 0 30 3 3211 0 99 18 +0 0 8463 ccssjs2 0 0 4 2 51 261 0 10 1 0 + 0 8537 ccssrr1 0 0 0 3 0 15 0 9 1 0 +0 8538 ccssch1 0 0 0 4 0 1 0 8 1 0 0 8757 sdbahh4 0 0 21 0 30 0 0 19 4 0 + 0 8853 sussfz1 0 0 10 0 4 0 0 21 2 0 + 0 9531 ccssrm1 0 0 0 139 0 27 0 574 4 0 + 0 9544 orarrd09 28 148 9568885 23818364 0 0 0 + 6708 0 0 0 9555 oratrd0u 0 0 3 0 0 0 0 2 0 0 +0 9607 oraprd0u 33 288 35538344 120434560 0 0 0 + 9509 0 0 0 9851 ppswp01 0 0 0 2 0 0 0 3 0 0 0 Jun 1 03:20 2007 TOTAL COMMAND SUMMARY FOR 05/2007 Page 1 TOTAL COMMAND SUMMARY COMMAND NUMBER TOTAL TOTAL TOTAL MEAN MEAN + HOG CHARS BLOCKS NAME CMDS KCOREMIN CPU-MIN REAL-MIN SIZE-K CPU-MIN +FACTOR TRNSFD READ TOTALS 32403945 2759238656.00 38978.47 11068820.00 70788.78 0.00 + 0.00 4362452336640 90950944 oracle 134522 1455575040.00 8026.35 2512456.00 181349.64 0.06 + 0.00 817459494912 51434296

In the foreach loop, I need to compare the Date after “MONTHLY USAGE FOR “ – in this case 05/2007 – to the 3rd argument I am passing to the perl script. If the dates do not match, I need the foreach loop to move on to process the next file in the directory. If the dates do match, I need to process the file (outputting lines from the MONTHLY USAGE FOR section) until the line that has “TOTAL COMMAND SUMMARY” in it – at this point, I need to exit the foreach loop and process the next file in the directory.

The perl code I had used to process a single PS Accounting Report file and output the appropriate records is as follows:

#!/usr/bin/perl use strict; use warnings; for my $file(“xsd00544.05”) { open (my $fh,'<',$file) or die "Cant open file $file: $!"; open (my $SORT,">","PSATst1.tab") or die "Can't open sort output file: + $!"; my @data; my $server; my $date; my $offset; while (my $line = <$fh> { chomp($line); if (($line =~ /MONTHLY USAGE FOR/) and ($. < 4)) { $offset = index($line,"MONTHLY USAGE FOR"); $date = substr($line,$offset+18,7); $server = substr($line,$offset+30,8); } last if ($line =~ /TOTAL COMMAND SUMMARY/); next unless $line =~ /^\d/; # Only process lines that beg +in with digits push @data,$line; } my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map [ $_, (split)[1] ], @data; print $SORT “$server \t $date \t $_\n” for @sorted; close $fh or die "Cant close file $file: $!"; close $SORT or die "Cant close sorted output file : $!"; }

The perl code I am testing to read multiple files from a directory, parse each file to determine if the report matches the date desired is as follows:

#!/usr/bin/perl ###################################################################### +## # # Testreaddpsa.pl - perl script to read a directory and multiple mon +thly # PSA Accounting Reports # # Execution requires 3 arguments # 1) Directory where PSA Monthly Accounting files reside # 2) File Specification string # 3) Date Required in format mm/yyyy # # Example: # perl Testreaddpsa.pl /prod/home/rvokulic/acct "*.*" "05/2007" # ###################################################################### +## use strict; use warnings; my $directory = $ARGV[0]; my $filespec = $ARGV[1]; my $datewant = $ARGV[2]; my $SORTFILES; my $index; my $offset; my $date; my $server; my $count; my %usage; my $files = 0; my @data; my @SORTFILES; opendir DIR, $directory or die "can't open $directory: $!\n"; my @FILES = glob("$directory/$filespec"); @SORTFILES=sort(@FILES); $count = @SORTFILES; ########################################################## # # Read All Files In Directory to Find Those That Match Date # ########################################################## foreach $SORTFILES (@SORTFILES) { open (my $fh,'<',$SORTFILES) or die "Cant open file $SORTFILES: $!"; open (my $SORT,">>","Tst1.tab") or die "Can't open sort output file: $ +!"; while (my $line = <$fh>) { chomp($line); next if ($line =~ /^$/ ); # skip if line begins with spaces last if ($line =~ /TOTAL COMMAND SUMMARY/); ## if (($line =~ /MONTHLY USAGE FOR/) and ($. < 4)) { $offset = index($line,"MONTHLY USAGE FOR"); $date = substr($line,$offset+18,7); $server = substr($line,$offset+30,8); last if ($date ne $datewant); ## } push @data, $line; my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map [ $_, (split)[1] ], @data; print $SORT "$server \t $date \t $_\n" for @sorted; } ## END of while loop continue { $files++ if eof; } close $fh or die "Cant close file $SORTFILES: $!"; close $SORT or die "Cant close file $SORT: $!"; } ## END of foreach loop closedir DIR;

This code is selecting the proper files that match the requested date, but no records are being output to the $SORT filehandle. I believe this has something to do with the scopes of the variables, but I am too new to perl to be sure.

I would greatly appreciate it if someone could give some insight as to what my problem might be.

Replies are listed 'Best First'.
Re: Reading Directory & Passing Files in Directory Into a Foreach Loop
by atemon (Chaplain) on Sep 03, 2007 at 17:11 UTC
    an you plz see if there is at least one match which will be false for this check. last if ($date ne $datewant); i.e there is at least one case where there is $date and $datewant are equal

      I am not sure what you are getting at here. When reading this particular directory, there will be both files in which the date will match and files in which the date will not match.

Re: Reading Directory & Passing Files in Directory Into a Foreach Loop
by Anonymous Monk on Sep 03, 2007 at 16:24 UTC
    closedir DIR or die "Can't closedir $directory : $!";
Re: Reading Directory & Passing Files in Directory Into a Foreach Loop
by Anonymous Monk on Sep 03, 2007 at 16:31 UTC
    while(<$fh>) is glob
      while(<$fh>) is NOT glob