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

I've got a large folder of over 9000 files all of which are pages in books. The name of the book is contained in the name of the file (i.e. unknown_U036_Box 02_Analysis Neutral final State Reaction Bradley Werner_0045) where "Analysis Neutral final State Reaction Bradley Werner" is the name of the book and "0045" is the page number. There are many different books in the folder. I'm trying to categorize the pages in folders based on the book title. The idea is that a file, such as the one named above, would get moved into a folder called "Analysis Neutral final State Reaction Bradley Werner". Here's what I've got.
$dir = getcwd(); find(\&book, $dir ."/Book Chapter"); my @bookFiles; sub book{ next if (-l && !-e ); push (@bookFiles, $File::Find::name) if (( $_ =~ m/\.txt$/) || ($_ + =~ m/\.jpg$/) || ($_=~ m/\.tif$/)); } my @bookNameArray; my $bookName; my @bookFileName; for(my $h = 0; $h < scalar(@bookFiles); $h++){ @bookNameArray = split(/_/ , $bookFiles[$h]); @bookFileName = split("/" , $bookFiles[$h]); $bookName = $bookNameArray[-2]; mkdir( $dir . "/Book Chapter/" . $bookName); move($bookFiles[$h], $dir . "/Book Chapter/" . $bookName . "/" . $b +ookFileName[-1]); }
It's moving most of the files into the folders perfectly, however, some are not getting moved at all. If I put a die command on the move function, it quits when I get to one it won't move. Any ideas on why it is not working?

Replies are listed 'Best First'.
Re: move() error
by toolic (Bishop) on Feb 26, 2010 at 17:56 UTC
    Check the return status of the move function (I assume you are using File::Copy):
    move($bookFiles[$h], $dir . "/Book Chapter/" . $bookName . "/" . $b +ookFileName[-1]) or warn $!;
    Typical reasons are: the input file is not found or you do not have permissions to write to the directory or clobber an existing file.

    From the File::Copy docs:

    All functions return 1 on success, 0 on failure. $! will be set if an error was encountered.
    You should also check the return status of the preceding mkdir.
      The error I'm getting says "No such file or directory" when I use the warning. However, I can verify that it does exist because I can find the file myself. I'm even printing out the old and new file paths when I run the script. It all seems to be correct. Suggestions?
        use strict and warnings and use lots of print's and file checks (-e):
        my @bookNameArray; my $bookName; my @bookFileName; for(my $h = 0; $h < scalar(@bookFiles); $h++){ @bookNameArray = split(/_/ , $bookFiles[$h]); @bookFileName = split("/" , $bookFiles[$h]); $bookName = $bookNameArray[-2]; my $newdir = $dir . "/Book Chapter/" . $bookName; print "newdir >>>$newdir<<<\n"; mkdir($newdir) or die "cant mkdir $newdir: $!"; my $src = $bookFiles[$h]; print "src>>>$src<<<\n"; my $dst = $dir . "/Book Chapter/" . $bookName . "/" . $bookFileName +[-1]); print "dst>>>$dst<<<\n"; if (-e $src) { print "$src exists\n"; } else { print "$src does not exist\n"; } # same -e check for dst move($src, $dst) or die "cant move : $!"; }
        See also Basic debugging checklist
        Suggestions?

        Heed the error, its doesn't lie

Re: move() error
by almut (Canon) on Feb 26, 2010 at 17:55 UTC
    If I put a die command on the move function, it quits...

    The docs claim that $! is being set on error, so what diagnostic do you get if you print $!?

Re: move() error
by pileofrogs (Priest) on Feb 26, 2010 at 19:52 UTC

    Dollars to doughnuts, the failures occur because the destination directory doesn't exist. Either it's not being made, it's being made but the name doesn't match up. All those spaces in the names could cause headaches, and there's always a chance you have weird non-printing characters in there.

    --Pileofrogs