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

Here's my problem:

I use "foreach $FILE (@files)" to read all the files from a certain directory. Now, inside this for, I call a "system" command, and when I control+C inside that command, I jump out of the foreach loop.

The problem now is, after jumping out, the directory is slightly altered, files have been moved, but if I do another foreach after the 1st one, it only sees the files that were there BEFORE the 1st foreach.

I think that sounded a little confusing, but here's the meat: I have 2 files, I enter the 1st foreach, inside it I move one of them. I jump out of the 1st foreach, then when entering the 2nd it still sees 2 files, when there's only one there.

Replies are listed 'Best First'.
Re: Problem reading files from directory
by shigetsu (Hermit) on Jul 20, 2007 at 18:48 UTC

    It's difficult to say where it goes wrong without some essential code provided; would you mind posting the relevant code bits?

    (enclose them in code tags please)

      Right, sorry.
      opendir(DIR, $INDIR) @mp3files = <*.mp3>; $OUTDIR = "./NEWDIR"; foreach my $FILE (@mp3files) { my $tmp= system("wine ......."); move($INFILE,"$OUTDIR/$INFILE"); if ($tmp!=0) { last; } } foreach my $FILE (@mp3files) { printf "File: %s\n",$FILE; } closedir(DIR);
      Now, when i press ctrl+c when wine is running, it jumps out of the 1st foreach. But at least one of the files has already been moved. When printing in the second foreach, it prints ALL files that were there, even the one that's been moved.

        First of, you should probably be using strictures (place them after the shebang line (usually #!/usr/bin/perl) separated by a blank line):

        use strict; use warnings;

        foreach will just iterate over a list given. Since you don't modifiy @mp3files anywhere, the contents will remain the same (i.e. untouched) in your second iteration.

Re: Problem reading files from directory
by TOD (Friar) on Jul 21, 2007 at 02:11 UTC
    apart from the circumstance that wine is not just a system call ;), i suggest you localize a hook for $SIG{TERM}, which is what Ctrl-C signals. e.g.:
    local $SIG{TERM} = sub { print STDERR "Got SIG{TERM}! Abort execution? + (y/n)"; my $c = getc; chomp $c; exit 0 if lc($c) eq 'y'; };
    --------------------------------
    masses are the opiate for religion.
      sry, it's $SIG{INT}, not $SIG{TERM}.
      --------------------------------
      masses are the opiate for religion.
Re: Problem reading files from directory
by mjscott2702 (Pilgrim) on Jul 23, 2007 at 21:23 UTC
    As already noted, you needed to read the directory contents again. The use of the <*.mp3> globbing operator can cause some unwanted side-effects, at least in my experience (maybe on older versions of Perl?). The problem is that the shell is used to do the filename expansion, and if there are lots of files that match, the list can be truncated. I usually use something like:
    opendir(INDIR, "$INDIR"); @mp3files = grep(/\.mp3$/, readdir(INDIR));
    to avoid this potential pitfall. If you only have a small number of files, shouldn't be a problem.