Dateien synchronisieren, sichern oder spiegeln

Vor ein paar Tagen ging es darum mehrere Verzeichnisse, in denen sich Backups befanden, in einem geplanten Task auf ein Netzlaufwerk zu kopieren. Die Erzeugung der Backups war jetzt so eingestellt, dass nur die letzten x-Backups behalten wurden und ältere automatisch gelöscht werden. Dieser Umstand muss jetzt natürlich auch beim Kopieren berücksichtigt werden, denn je nach Backupgröße kann es dann schnell zu Speicherplatzproblemen auf dem Zieldatenträger kommen. Als Entwickler denkt man sich: Dann schreib ich mir jetzt mal schnell ein Skript 😉 Es geht aber auch einfacher und zwar mit Robocopy. Dieses Programm spiegelt große Verzeichnisbäume inkrementell auf externe Festplatten oder Netzlaufwerke, setzt unterbrochene Übertragungen fort und lässt sich natürlich auch per Taskplaner automatisieren. Und das Beste: es gehört zu den Bordmitteln von Windows.

Jeder der schon einmal größere Dateien von A nach B kopieren wollte, z.B. auf einen zweiten Rechner im Netzwerk, hat bestimmt schon gemerkt, dass die Standard-Tools von Windows da schnell an ihre Grenzen kommen. Der Windows-Explorer kommt aus dem Tritt wenn es sich um viele kleine Dateien handelt, die Datei nicht lesbar ist, der Anwender keinen Zugriff auf sie hat oder die Netzwerkverbindung kurz unterbrochen wird. Zuverlässiger ist hier schon xcopy, aber Verzeichnisse exakt zu spiegeln oder inkrementell zu aktualisieren ist mit diesem Tool auch nicht möglich. Und hier kommt dann Robocopy ins Spiel. Robocopy ist eine Anwendung zur Dateireplikation und kann Dateien auf einem einzelnen Computer oder in einem Netzwerk kopieren. Das funktioniert mit

  • einer einzelnen Datei oder Ordner
  • einer kompletten Ordnerstruktur (inkl. aller Unterordner)
  • einer Ordnerstruktur inkl. Unterordner bis zu einer vorher festgelegten Verzeichnistiefe
  • inkl. einer Vielzahl von Filtern und Selektionsmöglichkeiten

Dabei arbeitet Robocopy stets inkrementell: Es vergleicht zunächst den Inhalt des Quellordners mit dem Ziel und kopiert dann nur die Dateien, die noch nicht im Zielordner vorhanden oder neuer sind. Dabei betrachtet Robocopy standardmäßig den Zeitpunkt der letzten Änderung sowie die Größe der Datei und kopiert nur wenn zu der Zieldatei eine Zeit- oder Größendifferenz besteht. Dies spart natürlich Zeit und auch Bandbreite (gerade mit langsamen Netzwerkverbindungen ist das ein ziemlich cooles Feature). Das Ganze hat aber auch einen Nachteil: Bei Robocopy handelt es sich um ein Kommandozeilenprogramm mit einem ziemlich großen Funktionsumfang und dementsprechend lang ist auch die Liste der zur Verfügung stehenden Parameter. Daher werde ich hier nur mal die wichtigsten Parameter auflisten. Am Ende des Beitrags (in den Weblinks) sind einige Quellen angegeben, die alle Parameter von Robocopy näher beschreiben.

Grundsätzlich sieht der Aufruf von Robocopy wie folgt aus:

robocopy <Source> <Destination> [<File>[ ...]] [<Options>]

  • Source – ist das Quellverzeichnis
  • Destination – ist das Zielverzeichnis
  • File – hier werden die Datei oder Dateien angegeben, die kopiert werden sollen. Die Verwendung von Wildcards (* oder?) ist ebenfalls möglich. Ist der File-Parameter nicht angegeben wird standardmäßig *.* verwendet
  • Options – Optionen, die für den Kopiervorgang genutzt werden sollen

Hier mal die wichtigsten Parameter für Robocopy (Quelle mit vollständiger Liste in den Weblinks):

OptionBeschreibung
/SKopiert Unterverzeichnisse (außer leere Verzeichnisse)
/EKopiert Unterverzeichnisse (auch leere Verzeichnisse).
/LEV:nKopiert nur bis zu einer Verzeichnistiefe von n.
/PURGELöscht Dateien und Verzeichnisse im Ziel-Verzeichnis, die im Quell-Verzeichnis nicht mehr vorhanden sind.
/MIRSpiegelt ein komplettes Verzeichnis. Löscht also auch Dateien im Ziel, die in der Quelle nicht mehr vorhanden sind (entspricht "/E" mit "/PURGE")
/MAX:nDateien, die größer als n Bytes sind, werden nicht kopiert.
/MIN:nKopiert keine Dateien, die kleiner als n Bytes sind.
/MAXAGE:nKopiert keine Dateien, die älter als n Tage sind. Sie können n auch als Datum in der Form von YYYYMMDD angeben.
/MINAGE:nKopiert keine Dateien, die neuer sind. Syntax wie oben.
/MAXLAD:nn spezifiert das maximale Datum des letztes Zugriffs - schließt Dateien aus, die seit n nicht verwendet wurden
/MINLAD:nn spezifiziert das minimale Datum des letzten Zugriffs - schließt Dateien aus, die seit n verwendet wurden
/r:nN definiert die maximalen Fehler, die beim Kopieren übergangen werden (standardmäßig 1 Mio.).
/w:nn definiert die Sekunden, die gewartet wird, wenn ein Kopiervorgang nicht erfolgreich war, um es erneut zu versuchen.
/log:LogFileSpeichert das Log in der definierten Datei.
/log+:LogFileHängt das Log an einer bereits bestehenden Logdatei an.

Das wären mal die wichtigsten Parameter, die bei einem Kopiervorgang angegeben werden können (für die vollständige Liste siehe Weblinks). Für die im Eingang beschriebene Problemstellung (Spiegeln des Backup-Verzeichnisses) reicht also die folgende Zeile:

robocopy [Quelle] [Ziel] /MIR

robocopy y:\BackupFolder z:\TargetBackupFolder /MIR

Falls die Pfade Leerzeichen enthalten, muss der Pfad in Anführungszeichen gesetzt werden.

robocopy "y:\Backup Folder" "z:\Target Backup Folder" /MIR

Das ganze packt man jetzt noch in ein Powershell- oder Batch-Skript und plant es als Task ein. Fertig! Ich glaube schneller kann man sich kein Skript zum spiegeln eines Verzeichnisses erstellen. Wenn man jetzt noch die ganzen Optionen bedenkt, die Robocopy bietet wäre ein eigen implementiertes Programm/Skript um einiges komplizierter geworden (von den ganzen Tests mal abgesehen). Also ein wirklich nützliches Tool und funktioniert bisher problemlos!

Literaturverzeichnis und Weblinks

Abk.Quelle
[1]Robocopy
[2]YARCGUI (GUI für Robocopy)
[3]How to: Copy very large files across a slow or unreliable network
[4]Robocopy – der Kopier-Gigant
Fork me on GitHub