[Dresden-pm] Frage zum rekursiven Kopieren von Verzeichnissen

Martin Probst ml at megamaddin.org
Di Dez 9 13:36:25 PST 2014


Hallo Hans-Dietrich,

> On 09 Dec 2014, at 07:29, Hans-Dietrich Kirmse <hd.kirmse at gmx.de> wrote:
> 
> Guten Morgen,
> 
> [...]
> Leider kopiert dieses Script nur Dateien, aber keine Verzeichnisse.
> Ich weiss zwar, dass es das Modul File::Copy::Recursive gibt, aber es müssen auch die Rechte gesetzt werden (das kann vielleicht auch noch entfallen), aber es muss auf jeden Fall der Owner geändert werden. Und wie man das mit Perl für einen Verzeichnis rekursiv macht, habe ich nicht gefunden. Auch wenn es hier vermutlich nicht gebraucht wird, bei den Rechten sollten ja eigentlich die für Dateien und Verzeichnisse unterschiedlich gesetzt werden. Auch das weiss ich nicht, wie man das machen könnte.
> 
> Zusammengefasst: es geht um das Ersetzen des 'TODO's in dem folgenden Abschnitt:
> 
> # wenn Datei
> if (-f $quelldatei) {
>  # dann kopieren (gegebenenfalls überschreiben)
>  $okay = copy $quelldatei, $zieldatei;
>  # wenn das Kopieren geklappt hat
>  if ($okay) {
>    # den Owner und Gruppe setzen
>    chown $uid, $gid, $zieldatei;
>    # die Rechte setzen
>    chmod 0755, $zieldatei;
>    # den Dateizähler um 1 erhöhen
>    $anz_files++;
>  }	
> }
> # sonst (wenn Verzeichnis)
> else {
>  #
>  # TODO  (analog für Verzeichnisse, aber eben rekursiv)
>  #
> }		
> 
> 
> Wäre für jeden Hinweis zu diesem Problem sehr dankbar.
> 
> PS: da ich als Laie und Autodidakt und zudem hier "im eigenen Saft schmore" würde ich mich auch über jeden Hinweis bzw. Kritik zu diesem Script unabhängig von diesem Kopierproblem freuen.

Als erster Tipp, nutze für die einzelnen Aufgaben doch sub’s. Das macht das Script an sich übersichtlicher und besser lesbar.

Ich würde ähnlich wie du herangehen, also Verzeichniseinträge lesen, Test ob Verzeichnis oder Datei und dann kopieren. Ich würde dafür jedoch eine rekursive Funktion nutzen, die diese Aufgabe erledigt. Es sollte quasi immer, wenn die Quelle ein Verzeichnis ist, ein einlesen des Verzeichnis, Test ob Datei... usw. usf. stattfinden.

Meine Q&D Lösung sieht daher in Perl so aus:

#!/usr/bin/perl

use strict;
use warnings;
use File::Copy;
use v5.10;

my $src = $ARGV[0];
my $dst = $ARGV[1];

mycopy($src, $dst);

sub mycopy {
    my $s = shift;
    my $d = shift;

    if(-d $s) {
        unless(-d "$d") {
            warn "$d is not a directory";
            return;
        }
        opendir(my $dh, $s) or die "Can't open dir $s: $!";
        while(my $ent = readdir($dh)) {
            next if($ent =~ m/^\.|\.\.$/);
            if(-d "$s/$ent") {
                mkdir("$d/$ent");
                chown(1337, 42, "$d/$ent");
                chmod(0755, "$d/$ent");
            }
            mycopy("$s/$ent", "$d/$ent");
        }
        closedir($dh);
    } else { # we assume that source must be a regular file
        $d = "$d/$s" if(-d $d);
        copy($s, $d);
        chown(1337, 42, "$d");
        chmod(0644, "$d");
    }
}

Aber mal anders gefragt, wenn du sowieso auf einem Linux-System bist, was spricht gegen ein Shell-Skript?

Viele Grüße,
Martin


Mehr Informationen über die Mailingliste Dresden-pm