Die Webseiten der Fachschaft Informatik am ERG Saalfeld


Verzeichnis kopieren

Für den bei uns eingesetzten Schulserver "delixs" trat in der Entwicklerliste folgendes Problem auf: es sollte bei mehreren Schülern der Desktop neu erstellt werden. Dazu war folgender Ansatz gewählt: von einem 'perfekt' eingerichteten Desktop als Muster sollten alle Dateien und Verzeichnisse einschließlich Unterverzeichnisse samt Inhalt kopiert und dabei die Eigentümer und Rechte richtig gesetzt werden. Obwohl das in meinen Augen eine Standardaufgabe war, fand sich dazu im CPAN keine Lösung. Zwar finden sich Lösungen zum Kopieren (auch rekursiv) und auch zum Ändern der Eigentüme (auch rekursiv), aber nicht zum korrekten Setzen der Rechte. Hierbei sollten die Rechte für Verzeichnisse und Dateien unterschiedlich gegeben werden - Verzeichnisse müssen ausführbar sein, Dateien sollten es hier nicht. An eine Lösung, die alle diese Forderungen auf einem Schlag erledigt, war überhaupt nicht zu denken. Auch mit den Bordmitteln von Linux war eine (einfache) Lösung nicht zu erstellen.

Auf eine Nachfrage in der Liste der Perl Mongers Dresden stellte mir Martin Probst eine Lösung zur Verfügung, die rekursiv ein vorgegebenes Verzeichnis kopiert und dabei die Eigentümer ändert und die Rechte neu setzt (für Verzeichnisse und Dateien getrennt). Dieses Script wird hier didaktisch vereinfacht und auf das rekursive Kopieren reduziert angegeben.

 

Programm

use strict;
use warnings;
use File::Copy;

my $quelle = $ARGV[0];
my $ziel   = $ARGV[1];

&mycopy($quelle, $ziel);


##### Ende des Hauptprogramms #####

sub mycopy {
  my $src  = shift;          # src  - source - Quelle
  my $dest = shift;         # dest - destination - Ziel

  # wenn $src ein Verzeichnis ist
  if (-d $src) {
    # wir öffnen das Verzeichnis
    opendir(my $dh, $src) or die "Can't open dir $src: $!";   # $dh - "Directory-Handle"
    # wir lesen das Verzeichnis ein
    while (my $entry = readdir($dh)) {
      # wenn der Eintrag ein '.' oder '..' ist, dann weiter
      if ($entry =~ m/^(\.\.|\.)$/) {
        next;
      };
      # wenn der Eintrag ein (Unter-)Verzeichnis ist
      if (-d "$src/$entry") {
        # dann legen wir im Zielverzeichnis ein entsprechendes (Unter-)Verzeichnis an
        mkdir "$dest/$entry";
      }
      # wir kopieren den Inhalt dieses Verzeichnisses
      &mycopy("$src/$entry", "$dest/$entry");
    }
    # wir schliessen das Verzeichnis
    closedir($dh);
  }
  # wenn $src kein Verzeichnis ist (also eine Datei)
  else {
    &File::Copy::copy($src, $dest);
  }
}

__END__

 

Das Script wurde um zwei print-Anweisungen ergänzt und für eine ordentliche Ausgabe in 3 Zeilen geändert. Der Aufruf sah bei mir dann so aus:

 

Aufgaben

  1. Bringen Sie das Programm zum Laufen. Hinweis: dieses Programm liefert noch keine Ausgabe!
  2. Ergänzen Sie das Programm mit 2 print-Anweisungen, dass eine Ausgabe ähnlich wie in dem Screenshot erfolgt.
  3. Geben Sie an, wo der rekursive Aufruf erfolgt.
  4. Geben Sie die Abbruchbedingung an.
  5. Ändern Sie das Programm so ab, dass statt dem Slash als Pfadtrenner der unter Windows übliche Backslash verwendet wird (wie im Screenshot zu sehen).
  6. Kopieren Sie ihr Verzeichnis "Dokumente" mit diesem Programm in ein Verzeichnis auf den Desktop. Hinweis: ermitteln Sie den Namen des Verzeichnisses mit "dir"!
  7. Ändern Sie das Programm so ab, dass das Zielverzeichnis angelegt wird, wenn es noch nicht existiert.

 

zurück


© ERG Saalfeld   -   Hans-Dietrich Kirmse   25.05.2015