¿Cómo puedo copiar un directorio de forma recursiva y filtrar nombres de archivos en Perl?

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

Pregunta

¿Cómo copio un directorio, incluidos los subdirectorios, excluyendo los archivos o directorios que coinciden con una determinada expresión regular en un sistema Windows?

¿Fue útil?

Solución

Haría algo como esto:

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;
}

Otros consejos

Otra opción es File :: Xcopy. Como su nombre lo indica, emula más o menos el comando xcopy de Windows, incluido su filtrado y las opciones recursivas.

De la documentación:

    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");

Si está en un sistema operativo similar a Unix y tiene acceso a rsync (1) , debe usarlo (por ejemplo, a través de system () ).

Perl's File :: Copy está un poco dañado (no copia los permisos en los sistemas Unix, por ejemplo), así que si no quiere usar las herramientas de su sistema, consulte CPAN. Tal vez File :: Copy :: Recursive podría ser útil, pero No veo ninguna opción de exclusión. Espero que alguien más tenga una mejor idea.

No sé cómo hacer una exclusión con una copia, pero podría trabajar algo como:

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

Una respuesta clásica usaría ' cpio -p ':

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

El comando ' cpio ' se ocupa de la copia real, incluida la preservación de permisos. El truco de ' cd $ SOURCE_DIR; encontrar . ... 'trata de eliminar la parte principal de la ruta de origen de los nombres. El único problema con esa invocación de ' find ' es que no seguirá los enlaces simbólicos; debe agregar ' -follow ' si eso es lo que quiere.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top