Como posso copiar um diretório de forma recursiva e nomes de arquivos de filtro em Perl?

StackOverflow https://stackoverflow.com/questions/227613

Pergunta

Como faço para copiar um diretório, incluindo sub-diretórios excluindo arquivos ou diretórios que correspondem a uma determinada regex em um sistema Windows?

Foi útil?

Solução

Eu faria algo assim:

use File::Copy;
sub copy_recursively {
    my ($from_dir, $to_dir, $regex) = @_;
    opendir my($dh), $from_dir or die "Could not open dir '$from_dir': $!";
    for my $entry (readdir $dh) {
        next if $entry =~ /$regex/;
        my $source = "$from_dir/$entry";
        my $destination = "$to_dir/$entry";
        if (-d $source) {
            mkdir $destination or die "mkdir '$destination' failed: $!" if not -e $destination;
            copy_recursively($source, $destination, $regex);
        } else {
            copy($source, $destination) or die "copy failed: $!";
        }
    }
    closedir $dh;
    return;
}

Outras dicas

Outra opção é File :: Xcopy. Como o nome diz, é mais ou menos emula as janelas comando xcopy, incluindo a sua filtragem e opções recursiva.

A partir da documentação:

    use File::Xcopy;

    my $fx = new File::Xcopy; 
    $fx->from_dir("/from/dir");
    $fx->to_dir("/to/dir");
    $fx->fn_pat('(\.pl|\.txt)$');  # files with pl & txt extensions
    $fx->param('s',1);             # search recursively to sub dirs
    $fx->param('verbose',1);       # search recursively to sub dirs
    $fx->param('log_file','/my/log/file.log');
    my ($sr, $rr) = $fx->get_stat; 
    $fx->xcopy;                    # or
    $fx->execute('copy'); 

    # the same with short name
    $fx->xcp("from_dir", "to_dir", "file_name_pattern");

Se acontecer de você estar em um Unix-like OS e ter acesso a rsync (1), você deve usá-la (por exemplo, através system()).

Arquivo do Perl :: Copy é um pouco quebrado (ele não copia permissões em sistemas Unix, por exemplo), então se você não quiser usar suas ferramentas de sistema, olhada CPAN. Talvez File :: cópia :: recursiva poderia ser útil, mas não vejo qualquer opções de exclusão. Espero que alguém tem uma idéia melhor.

Eu não sei como fazer uma exclusão com uma cópia, mas você poderia trabalhar em algo ao longo das linhas de:

ls -R1 | grep -v <regex to exclude> | awk '{printf("cp %s /destination/path",$1)}' | /bin/sh

A resposta clássica usaria 'cpio -p':

(cd $SOURCE_DIR; find . -type f -print) |
perl -ne 'print unless m/<regex-goes-here>/' |
cpio -pd $TARGET_DIR

Os 'cpio' ofertas de comando com a cópia real, incluindo a preservação permissão. O truque de negócios 'cd $SOURCE_DIR; find . ...' com a remoção da parte principal do caminho de origem dos nomes. O único problema com essa invocação de 'find' é que ele não vai seguir os links; você precisa adicionar '-follow' se é isso que você quer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top