2008-10-22 11 views

Antwort

11

ich tun würde:

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

Ich denke, Sie haben ein Problem (Endlosschleife) für den Fall, dass Ihre $ regexp nicht passt "." oder "..", die die ersten beiden Werte von $ entry sind, die von readdir zurückgegeben werden. Wenn Ihr $ to_dir nicht existiert und eine $ source tatsächlich ein Verzeichnis ist, wird mkdir fehlschlagen, ich rate Ihnen stattdessen mkpath zu verwenden. – huitseeker

+0

. und ... sind unter Windows AFAIK kein Problem, also sollte das kein Problem sein, aber für die Portabilität hast du recht, es wäre besser, diese herauszufiltern. Wie für mkpath: persönlich denke ich, dass eine solche Situation einen Fehler geben sollte, aber das ist Geschmackssache. –

1

Ich weiß nicht, wie man mit einer Kopie einen Ausschluß zu tun, aber man kann etwas nach oben entlang der Linien der Arbeit:

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

Wenn Sie auf einem Unix-ähnliches Betriebssystem geschehen zu sein und Zugang hast zu rsync (1), sollten Sie das verwenden (zum Beispiel durch system()).

Perls File :: Copy ist ein bisschen kaputt (es kopiert keine Berechtigungen auf Unix-Systemen zum Beispiel). Wenn Sie also Ihre Systemtools nicht verwenden wollen, schauen Sie sich CPAN an. Vielleicht könnte File::Copy::Recursive von Nutzen sein, aber ich sehe keine Ausschlussoptionen. Ich hoffe, jemand anderes hat eine bessere Idee.

9

Eine weitere Option ist File :: Xcopy. Wie der Name schon sagt, emuliert er mehr oder weniger den Befehl windows xcopy, einschließlich seiner Filter- und rekursiven Optionen.

Aus der Dokumentation:

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

Eine klassische Antwort würde verwenden 'cpio -p ':

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

Die' cpio' Befehl befasst sich mit dem eigentlichen Kopieren, einschließlich Genehmigung Erhaltung. Der Trick von 'cd $SOURCE_DIR; find . ...' behandelt das Entfernen des führenden Teils des Quellweges von den Namen. Das einzige Problem mit diesem Aufruf von 'find' ist, dass es Symlinks nicht folgen wird; Sie müssen "-follow" hinzufügen, wenn Sie das möchten. so etwas wie dieses

+0

funktioniert das auch auf Windows? – Manu

Verwandte Themen