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

I don't know why, but my script removes files from my directory when I'm mass renaming. When there's only say 500 files, it renames them all just fine. When there's say 2000+ it messes up somewhere and some files vanish. The or die is not picking anything up so I'm not sure what or where things are going wrong.

Anyone have any pointers?

opendir(DIR, $dir) || die "can't opendir $dir: $!"; my @files =grep { /\.jpg$/i || /\.gif/i || /\.png/i || /\.bmp/i || /\ +.jpeg/i} readdir(DIR); closedir DIR; foreach my $file (@files) { my $ext; $file =~ m/(.[^.]+)$/; $ext = $1; $cnt++; rename $file, "$cnt$ext" or die $!; print "$file is now known as $cnt$ext\n"; }
Could it essentially be going too fast and renaming some to "" which causes Windows to delete them? I figured an error would appear somewhere if it failed to rename something.

Replies are listed 'Best First'.
Re: Renaming a group of files occassionally deletes some
by FunkyMonk (Bishop) on Jun 01, 2007 at 17:57 UTC
    I can't say if these problems are related to your files disappearing, but there are a couple of errors in your script:

    my @files =grep { /\.jpg$/i || /\.gif/i || /\.png/i || /\.bmp/i || /\ +.jpeg/i} readdir(DIR);

    Only the first of your regexs are anchored at the end of the filename. I'd use:

    my @files = grep { /\.(?:jpg|gif|png|bmp|jpeg)$/i } readdir(DIR);

    Later on, you

    $file =~ m/(.[^.]+)$/; $ext = $1;

    There's two mistakes here. The regex is wrong. You're matching any one character ("."), followed by at least one non-dot "[^.]+" at the end of the string "$". Then you assign the captured match to $ext without checking if a match was found. Don't do that.

    It may be you just haven't included them in your post, but you are running under warnings and strict, aren't you?

Re: Renaming a group of files occassionally deletes some
by blazar (Canon) on Jun 01, 2007 at 17:41 UTC
    Could it essentially be going too fast and renaming some to "" which causes Windows to delete them? I figured an error would appear somewhere if it failed to rename something.

    from perldoc -f rename:

    rename OLDNAME,NEWNAME Changes the name of a file; an existing file NEWNAME will be clobbered. Returns true for success, false otherwise.

    Use e.g. -f to check for the existence of the destination before possibly clobbering it.

      Sorry, the way it's worded is kind of strange. Is it saying that it will be clobbered if the file you're trying to rename to already exists in the directory?
        On Win32 and Linux, this test program shows that clobbering will happen.
        use strict; use warnings; my $file1 = 'file1.dat'; my $file2 = 'file2.dat'; for my $file ( $file1, $file2 ) { open my $fh, '>', $file or die; print {$fh} "Test data for file '$file'\n"; close $fh or warn; } rename $file1, $file2 or die;
        Output: Produces only one file, named `file2.dat`, containing "Test data for file1.dat"
Re: Renaming a group of files occassionally deletes some
by semio (Friar) on Jun 01, 2007 at 20:34 UTC
    I ran your script in a directory where there were multiple image file types, .bmp, .jpeg., etc. After this, I had exactly one remaining file for each image file type...the rest were quashed. Perhaps try adding an element of uniqueness when renaming your files, such as by adding a timestamp. I'm not sure of your exact circumstances, but this issue may only pop up when dealing with the large number of files you are working with. Try the following:

    foreach my $file (@files) { my $ext; $file =~ m/(.[^.]+)$/; $ext = $1; my $orig = $file; $orig =~ s/\..*$//; rename $file, time() . "($orig)" . $ext or die $!; }

    hope this helps. cheers.