2008-10-22 8 views

Respuesta

11

me gustaría hacer 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; 
} 
+0

Creo que tienes un problema (bucle infinito) en caso de que tu $ regexp no coincida con "." o "..", que son los dos primeros valores de $ entry devueltos por readdir. Si su $ to_dir no existe, y un $ fuente es de hecho un directorio, mkdir fallará, le aconsejo usar mkpath en su lugar. – huitseeker

+0

. y ... no son un problema en Windows AFAIK, por lo que no debería ser un problema, pero para la portabilidad tienes razón, sería mejor filtrarlos. En cuanto a mkpath: personalmente creo que tal situación debería dar un error, pero eso es una cuestión de gusto. –

1

No sé cómo hacer una exclusión con una copia, pero se puede trabajar algo a lo largo de las líneas de:

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

Si quieres pasar a ser en un sistema operativo similar a Unix y tener acceso a rsync (1), debe usar eso (por ejemplo, a través de system()).

Perl's File :: Copy está un poco roto (no copia los permisos en los sistemas Unix, por ejemplo), así que si no quiere usar las herramientas de su sistema, mire el 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.

9

Otra opción es File :: Xcopy. Como su nombre lo dice, emula más o menos el comando de Windows xcopy, incluidas sus opciones de filtro y 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"); 
1

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 

Los'' cpio ofertas de comando con la copia real, incluyendo la preservación permiso. El truco de 'cd $SOURCE_DIR; find . ...' trata de eliminar la parte principal de la ruta fuente de los nombres. El único problema con esa invocación de 'find' es que no seguirá enlaces simbólicos; necesita agregar '-follow' si eso es lo que desea.

+0

hace que el trabajo en las ventanas también? – Manu

Cuestiones relacionadas