views:

695

answers:

5

I have a Perl script that works on Windows XP. It uses File::Copy's move function to move a directory tree to another place on the same drive. The script fails (silently) on Windows 2008. Nothing moved, nothing deleted.

I am using ActiveState Perl 5.10.0 Build 1005 and the File::Copy that comes with it.

Anyone know of issues with ActiveState Perl on Windows 2008 that might cause this?

Example script:

use File::Copy;
print "Move AAA to ZZZ\n";

move("AAA", "ZZZ");

print "Done.\n";
+8  A: 
caskey
I do as you said and I get the following:Move failed: No such file or directory at C:\Users\pchernoch\Documents\test.pl line 4.Of course the file IS there, which begs the next question: why can't it find the file? The directory is in my own Documents directory and was created by me, so permissions should not be a problem.
Paul Chernoch
The script may not be running in the same directory as the files. Either the source or destination must not exist. Don't forget that if you're moving to /a/b/c, /a/b must already exist.
caskey
Surprisingly, the directories were created read only. Quite a different set of defaults than XP. Took me by surprise. I changed them to read/write, but still doesn't work.
Paul Chernoch
caskey, you may be onto something. I will see what happens if I create the target dir first. But I was hoping for a file mover that would create the directory structure for me.
Paul Chernoch
I can see where you would think that. Perl just doesn't do things that way. There are more pieces you can pick up to make it happen: http://perldoc.perl.org/File/Path.html
caskey
+4  A: 

If you don't want to have to check the return value, you can have autodie do it for you.

Since move() and copy() return a zero to indicate an error, and that's what autodie assumes, it's fairly straight forward.

use strict;
use warnings;
use File::Copy;

use autodie qw'copy move';

move("AAA", "ZZZ"); # no need to check for error, because of autodie

print "Done.\n";

Assuming that "AAA" doesn't exist, here is the output ( on STDERR ).

Can't move('AAA', 'ZZZ'): No such file or directory at test.pl line 7
Brad Gilbert
Never heard of autodie. Nice feature. Thanks.
Paul Chernoch
I tried move on a single file and it works. Must be something having to do with directories.
Paul Chernoch
Try giving it the full path, or relative path to current directory. You may be giving it just the file names. If you're parsing a folder, and using that to give the file name, you won't be getting either the full path, or the relative path.
Brad Gilbert
+1  A: 

I've had weird things happen to me on Windows with moving and removing files. The solution was to use the CPAN module File::Remove.

singingfish
I started looking for other Perl modules. File::Copy::Recursive looks promising. (It uses File::Copy to move individual files, but wraps it in a recursive script.) If I get it to work I will comment.The attraction of File::Copy is that it does a true file system move if it can, which is nearly instantaneous, whereas a Copy+Delete is slow. We are moving terabytes of data and it has to be fast.
Paul Chernoch
File::Copy::Recursive uses File::Copy::copy instead of move. Thus it does copy+delete instead of move. I will keep looking.
Paul Chernoch
+1  A: 

Rather than slog through another half dozen Perl modules looking for one that did what I wanted, I adopted a hybrid approach and called out to DOS to use the "move" command. DOS move has its own peculiarities. For example, if you copy c:\temp\AAA to c:\temp\BBB and BBB exists already, you get c:\temp\BBB\AAA. But if BBB does not already exist, you get c:\temp\BBB, with no AAA underneath it. To avoid that, I first create BBB (if it does not exist) and then delete it. This causes all the directories down to BBB to be created if absent.

Here is my code:

sub move($$) {
    my ($source, $target) = @_;

    if (! -d $source) {
     print "    ERROR: Source directory does not exist: $source. Not copying to $target.\n";
    }
    elsif (-d $target) {
     print "    ERROR: Target directory already exists: $target. Not copying from $source.\n";
    }
    else {
     $source =~ s|/|\\|g;
     $target =~ s|/|\\|g;
     my $results = `if not exist "$target" mkdir "$target" & rmdir "$target" & move /Y "$source" "$target"`;
     print "    Results of move \"$source\" \"$target\":\n $results\n";
    }
}
Paul Chernoch
+2  A: 

I just encountered this myself, and in my particular situation, despite the exact same error ("No such file..."), it was actually that I had a file, from deep within the hierarchy I was renaming, open in a text editor somewhere. As soon as I closed that file, the error stopped occurring.

Kev
Files opened by another process are a constant pain on Windows.
brian d foy

related questions