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

hi. i've wrriten an ftp program that every hour with check a directory for files and if there are any it will upload them then move them to a different folder. i get the file list like this.....

tie %Dir, IO::Dir, "p:/charts/Sendtray/." or &WriteToListView2("Error opening directory: $!");


foreach (keys %Dir) { unless ($_ eq "." or $_ eq ".." or $_ eq "GONE" or $_ eq "") { push(@FileList,$_); } }

then upload then move.

the first time the files are uploaded everything works fine. when it uploads a second time i keep on getting bad file descriptor errors with a space instead of a file name. because i can't remove the files from @FileList because they're uploaded in a foreach loop, i undef them after they're uploaded and moved....

foreach $oFile(@FileList) { if ($oFTP->put("p:/charts/Sendtray/$oFile")) { if (move("p:/charts/Sendtray/$oFile","p:/charts/Sendtray/G +ONE/$oFile")) { &LogSentFiles($oFile); $oFile = undef; } } }

so i figure the error is because of the undef working unlike how i expect it to. does anyone now how to stop this from happening?

Edit kudra, 2002-06-17 Added code tags to one paragraph per ntc request, line to try to preserve author's intent of keeping the two code bits apart

Replies are listed 'Best First'.
Re: a problem with arrays and undeffing i think
by kvale (Monsignor) on Jun 17, 2002 at 02:58 UTC
    If you want use $oFile = undef as a done flag, test to see if the @FileList entry equals undef before processing:
    foreach $oFile(@FileList) { next unless defined $oFile; if ($oFTP->put("p:/charts/Sendtray/$oFile")) { if (move("p:/charts/Sendtray/$oFile","p:/charts/Sendtray/G +ONE/$oFile")) { &LogSentFiles($oFile); $oFile = undef; } } }
    A cleaner way of representing your set of files is with a hash:
    foreach (keys %Dir) { $FileSet{$_}++ unless $_ eq "." || $_ eq ".." || $_ eq "GONE" || $_ eq ""; }
    Then as the files are moved, you may delete them from the hash.

    -Mark
Re: a problem with arrays and undeffing i think
by graff (Chancellor) on Jun 17, 2002 at 02:59 UTC
    Your description is a bit confusing:

    the first time the files are uploaded everything works fine. when it uploads a second time...

    If the files have been uploaded and moved the "first time", how is it possible that they come into play a "second time"?

    If you really are looping over @FileList only once (as I suspect you should be), then there should be no problem -- though a better approach might be (untested code here):

    my $src = "p:/charts/Sendtray/"; my $dst = "p:/charts/Sendtray/GONE/"; while (@FileList) { my $oFile = shift @FileList; $oFTP->put("$src$oFile") and move("$src$oFile","$dst$oFile") and &LogSentFiles($oFile) or warn "$oFile didn't move\n"; }
    If you are going through this list a second time for some other reason, then of course, having set the array elements to undef will cause the error report when you pass the empty elements as part of a string for the FTP->put().
      it only goes through the list once. theres a timer that is set to run &Outgoing_FTP but every hour when it starts uploading the files it will come up with the bad file descriptors error for the amount of files that were uploaded before, but, it won't print their file names, just a space.
        Have you done an independent check of directory contents before and after a given run? E.g. if it runs at 09:00, you should do a (gnu) "find" (or something equivalent) on the target directory a couple minutes before execution, and again a minute or so after execution.

        It may be that having %Dir tied with IO::Dir, while trying to modify the contents of the target directory, is causing unexpected side-effects (or failure to behave in the expected manner), and the problem is not with the @FileList array, but rather with the directory contents.

Re: a problem with arrays and undeffing i think
by greenFox (Vicar) on Jun 17, 2002 at 10:49 UTC

    Just guessing here but I suspect that you are failing to (re-)initialise @FileList between calls? Without seeing the rest of your code it is a bit hard to suggest the best approach but when you first use @FileList you need to initialise it my @FileList=(); and perhaps do so after you have processed the last file @FileList=(); depending on the scope of @FileList.

    It looks like you are not using strict, you should do that!

    --
    my $chainsaw = 'Perl';