dircopy и dirmove не работают должным образом

Я пишу сценарий Perl, который позволяет нам легко перемещать или копировать ОГРОМНЫЙ каталог (возможно, +100 000 подкаталогов) в другое место. Я использую File::Copy::Recursive для этой цели следующим образом (неполный! Некоторые переменные не определены, но это дает минимальное представление о том, что происходит):

use strict;
use warnings;

use File::Copy::Recursive qw(dircopy dirmove pathrmdir);
$File::Copy::Recursive::CPRFComp = 1;


my ($action, $source_location, $target_location) = @ARGV;
opendir(my $source_handle, $source_location) or die "Can't opendir $source_location: $!\n";
my $directories_found = 0;

while (my $sub_dir = readdir $source_handle) {
    unless (-d "$source_location/$sub_dir") {
        print STDERR "$source_location/$sub_dir not a dir\n";
        next;
    }
    # Makes sure we only move directories given a pattern defined elsewhere
    if ($sub_dir =~ $file_match_regex) {
        # $action is an input argument
        if ($action eq 'copy') {
            dircopy("$source_location/$sub_dir/", "$target_location/")
                or die "Cannot copy $source_location/$sub_dir/: $!\n";
        } elsif ($action eq 'move') {
            dirmove("$source_location/$sub_dir/", "$target_location/")
                or die "Cannot move $source_location/$sub_dir/: $!\n";
        }
        $directories_found = 1;
    } else {
        print STDERR "$source_location/$sub_dir did not match regex\n";
    }
}

if ($action eq 'move') {
    # Remove topmost directory
    pathrmdir($source_location)
        or die "Cannot remove $source_location: $!\n";
}

if (!$directories_found) {
    print STDERR "No items found to $action\n";
}

При первом запуске кажется, работает как положено. Возьмите эту команду

perl myscript.pl move source/ /home/otherdir/target/

Выход терминала

source/. did not match regex
source/.. did not match regex

и это все.

Однако, когда я запускаю тот же скрипт в перемещенной папке, все идет не так.

perl myscript.pl move /home/otherdir/target/ /home/failing/target/

/home/otherdir/target/. did not match regex
/home/otherdir/target/.. did not match regex
/home/otherdir/target/somefile1.txt not a dir
/home/otherdir/target/somefile2.txt not a dir
/home/otherdir/target/somefile3.txt a dir
/home/otherdir/target/somefile4.txt a dir

Очевидно, я не должен получать разные ответы при запуске одного и того же сценария копирования/перемещения данных. Примечательно, однако, что файлы берутся из одной директории (не могу понять, из какой они все одинаковые по содержанию), а остальные директории сохраняются. Таким образом, при каждом запуске для одного $sub_dir сценарий копировал содержимое каталога в место назначения, а не сам каталог. Это означает, что я теряю каталог при каждом запуске скрипта... Хотя я не понимаю, почему.

Я думаю, что я неправильно использую dircopy и dirmove , и я также не уверен, что $File::Copy::Recursive::CPRFComp = 1; верен (я не нашел документацию очень понятной для моих новичков). есть идеи?


После еще нескольких копаний я думаю, что это то, что происходит. Небольшая документация по CPRFComp читает (при условии, что «foo/file»):

dircopy('foo', 'bar') or die $!;
# if bar does not exist the result is bar/file
# if bar does exist the result is bar/file

$File::Copy::Recursive::CPRFComp = 1;
dircopy('foo', 'bar') or die $!;
# if bar does not exist the result is bar/file
# if bar does exist the result is bar/foo/file

Таким образом, я предполагаю, что первое действие копирования/перемещения подкаталога запускается до того, как существует целевое местоположение («bar» в примере), что приводит к bar/file, а не bar/foo/file. Затем вопрос меняется на: как я могу убедиться, что мои операции копирования/перемещения ждут, пока целевой каталог не будет построен?


person Bram Vanroy    schedule 10.10.2016    source источник
comment
Ваш код показывает, что вы печатаете $source_location/$sub_dir did not match regex, но ваше сообщение об ошибке показывает . did not match regex без косой черты. Таким образом, вы либо не показываете свой реальный код, либо не показываете свой реальный результат. Пожалуйста, покажите ваш фактический код и ваше фактическое сообщение об ошибке, иначе мы не сможем узнать, являются ли обнаруженные нами проблемы вашими реальными проблемами или просто результатом ошибочной публикации вашей проблемы.   -  person Paul L    schedule 10.10.2016
comment
@PaulL Я отредактировал пример. Я не совсем понимаю, почему за это проголосовали. Если мне нужно предоставить дополнительную информацию, пожалуйста, сообщите мне об этом.   -  person Bram Vanroy    schedule 11.10.2016


Ответы (1)


Просто чтобы убедиться, что путь существует до того, как какие-либо подкаталоги будут перемещены или скопированы в него, я просто создаю путь перед выполнением операции, используя make_path модуля File::Path. Просто, вот так:

if ($action eq 'copy') {
  make_path($target_location);
  dircopy("$source_location/$sub_dir/", "$target_location/")
        or die "Cannot copy $source_location/$sub_dir/: $!\n";
} elsif ($action eq 'move') {
  make_path($target_location);
  dirmove("$source_location/$sub_dir/", "$target_location/")
        or die "Cannot move $source_location/$sub_dir/: $!\n";
}
person Bram Vanroy    schedule 11.10.2016