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

I need the following code to look in a directory for all order files that begin with "ord.". Then, look at the order dates in each of these files, and if the ALL the dates are Mondays, move the file to the order_bad directory. As soon as I hit a non-Monday date, move the file to the order_good directory. Sounds rather simple, but my code is not moving the files that are all Mondays. I appologize in advance for the way this posting looks. This is my first time posting here and I can't seem to get it quite right.
use strict; use File::Copy; use Time::Local; use lib "/opt/perl/lib/site_perl/5.6.1/Mail"; use Mail::Sender; my $instance = "natt1"; my $instance_root = "/opt/manu/manu71/transport/$instance"; my $goodordpath = "$instance_root/order_good"; my $badordpath = "$instance_root/order_bad"; my $allmondayflag = 0; my $starttime = localtime; print "\n\n*** Starttime = $starttime ***\n\n"; if (-d "$instance_root/order_temp") { my $where = "$instance_root/order_temp"; print "Directory $where exists. Directory check was successful.\n\ +n"; # find the number of files we are to process my @count = (<$instance_root/order_temp/ord.*>); my $plural = (scalar(@count = (<$instance_root/order_temp/ord.*>) +) == 1) ? "" : "s"; print "Processing ", scalar @count, " order file$plural.\n"; # if there are no files to process, bail print "\nThere are no files to process. Now exiting.\n" if (@count + == 0); foreach my $orderfile (<$instance_root/order_temp/ord.*>) { print "\nProcessing Order File: $orderfile\n"; open (FILEH, $orderfile) or die "Could not open order file: $o +rderfile : $!"; $allmondayflag = 0; while (my $line = <FILEH>) # loop as long as there are +records in the file { my $ordertype = substr($line, 0, 2); # used to fin +d the order header if ($ordertype eq "HM") # only look at the dates o +n the header records { my $ordernum = substr($line, 2, 7); my $date_str = substr($line, 64, 8); my ($year, $month, $day) = $date_str =~ m/ +(\d{4})(\d{2})(\d{2})/; my $time = timelocal("", "", "", $day, $month-1, + $year); # For $month: Jan = 0, Feb = 1, etc. if ((localtime($time))[6] == 1 ) # the order is + on a Monday { print " Order Number = $ordernum Order Date += $date_str is a Monday\n"; $allmondayflag = 1; next; # move onto the next record } else { $allmondayflag = 0; print " Order Number = $ordernum Order Date += $date_str is not a Monday. This file is OK to move and process.\n"; # We have found a date that is not a Monday. T +his file is OK. We need to move it to be processed close FILEH; move("$orderfile", $goodordpath) or die "Could n +ot move the file $orderfile. Move failed: $!"; last; # bail out of the loop if date is not M +onday and process the next order } if ($allmondayflag) { print " Order Number = $ordernum has ord +er dates that are all Mondays. This is a bad order file and is being +moved to $badordpath\n"; move("$orderfile", $badordpath) or die " +\nCould not move the file $orderfile. Move failed: $!"; #$allmondayflag = 0; } } # end of Ordertype IF } # end of while loop # close file when we run out of lines to read close FILEH; } # end of ForEach loop } else { my $where = "$instance_root/order_temp"; print "Directory $where does not exist...now exiting\n\n"; } my $endtime = localtime; print "\n*** Endtime = $endtime ***\n\n";

Replies are listed 'Best First'.
Re: Seeking help with Looping problem
by imp (Priest) on Aug 15, 2006 at 18:21 UTC
    Inside your loop the logic is roughly as follows:
    if ((localtime($time))[6] == 1 ) { $allmondayflag = 1; next; } else { $allmondayflag = 0; last; } if ($allmondayflag) { # I never get run }
    I think you want to move the last condition outside the file reading loop.
      If I move the 'last' outside of the 'else', the good orders won't be moved as they are now. Am I correct?
        All of the moving should probably occur outside that loop.

        I would initialize the $allmondayflag = 1 before the loop, and set it to 0 for the first occurence of a non-monday.
        Then outside the file reading loop you can check the $allmondayflag and decide where to move the file to.

        Other than that your code looks pretty good, but I would add use warnings; to the top

Re: Seeking help with Looping problem
by GrandFather (Saint) on Aug 15, 2006 at 18:16 UTC

    Which files is your code moving? Can you reduce the code to something that demonstrates your problem and that can be run on someone elses system?

    An eyeball check of you code may well turn up errors of all sorts that may, or may not, include the immediate issue. But that takes a lot more time than debugging the code. Perl programmers are lazy don't you know - its a virtue.


    DWIM is Perl's answer to Gödel
      The order files that contain non-Mondays are being moved to the order_good directory. It's the all Monday orders that won't move. I'll see what I can do to clean up the code and repost.
Re: Seeking help with Looping problem
by jwkrahn (Abbot) on Aug 16, 2006 at 00:14 UTC
    This is *UNTESTED* but it should come close to what you want:
    #!/usr/bin/perl use warnings; use strict; use lib "/opt/perl/lib/site_perl/5.6.1/Mail"; use Mail::Sender; use File::Basename 'basename'; use POSIX 'mktime'; my $instance = 'natt1'; my $instance_root = "/opt/manu/manu71/transport/$instance"; my $goodordpath = "$instance_root/order_good"; my $badordpath = "$instance_root/order_bad"; my $where = "$instance_root/order_temp"; print "\n\n*** Starttime = " . localtime . " ***\n\n"; -d $where or die "Directory $where does not exist...now exiting\n\n"; print "Directory $where exists. Directory check was successful.\n\n"; # find the number of files we are to process # if there are no files to process, bail @ARGV = <$where/ord.*> or die "\nThere are no files to process. Now ex +iting.\n"; print 'Processing ' . @ARGV . ' order file', @ARGV == 1 ? '' : 's', ". +\n"; my ( $ordertype, $ordernum, $date_str, $time ); while ( <> ) { print "\nProcessing Order File: $ARG\n" if $. == 1; if ( /^HM(.{7})/ ) { $ordernum = $1; $date_str = substr $line, 64, 8; my ( $year, $month, $day ) = $date_str =~ /(\d{4})(\d{2})(\d{2 +})/; $time = mktime( 0, 0, 12, $day, $month - 1, $year - 1900 ); + # For $month: Jan = 0, Feb = 1, etc. } if ( ( localtime $time )[ 6 ] != 1 ) { print " Order Number = $ordernum Order Date = $date_str is + not a Monday. This file is OK to move and process.\n"; my $file = basename $ARGV; # save the file name before closin +g it! close ARGV; # close the file before moving it! rename "$where/$file", "$goodordpath/$file" or die "Could not +move the file $file. Move failed: $!"; next; } if ( eof ) { print " Order Number = $ordernum has order dates that are al +l Mondays. This is a bad order file and is being moved to $badordpath +\n"; my $file = basename $ARGV; # save the file name before closin +g it! close ARGV; # close the file before moving it! rename "$where/$file", "$badordpath/$file" or die "\nCould not + move the file $file. Move failed: $!"; } } print "\n*** Endtime = " . localtime . " ***\n\n";