Ich habe zwei Laufwerke mit den gleichen Dateien, aber die Verzeichnisstruktur ist völlig unterschiedlich.
Gibt es eine Möglichkeit, alle Dateien auf der Zielseite so zu verschieben, dass sie der Struktur der Quellseite entsprechen? Mit einem Drehbuch vielleicht?
Beispielsweise hat Laufwerk A:
/foo/bar/123.txt
/foo/bar/234.txt
/foo/bar/dir/567.txt
Während Laufwerk B hat:
/some/other/path/123.txt
/bar/doo2/wow/234.txt
/bar/doo/567.txt
Die fraglichen Dateien sind riesig (800 GB), daher möchte ich sie nicht erneut kopieren. Ich möchte nur die Struktur synchronisieren, indem ich die erforderlichen Verzeichnisse erstelle und die Dateien verschiebe.
Ich dachte an ein rekursives Skript, das jede Quelldatei auf dem Ziel findet, sie dann in ein passendes Verzeichnis verschiebt und sie bei Bedarf erstellt. Aber - das übersteigt meine Fähigkeiten!
Eine andere elegante Lösung wurde hier angegeben: /superuser/237387/any-way-to-sync-directory-structure-when-die-Dateien-sind- bereits-auf- beiden Seiten / 238086
Antworten:
Ich werde mit Gilles gehen und Sie auf Unison hinweisen, wie von Hasen J vorgeschlagen . Unison war DropBox 20 Jahre vor DropBox. Sehr solider Code, den viele Leute (ich selbst eingeschlossen) jeden Tag benutzen - es lohnt sich, ihn zu lernen. Trotzdem
join
braucht es all die Werbung, die es bekommen kann :)Das ist nur eine halbe Antwort, aber ich muss mich wieder an die Arbeit machen :)
Grundsätzlich wollte ich das wenig bekannte
join
Hilfsprogramm demonstrieren, das genau das macht: Verbindet zwei Tabellen in einem bestimmten Feld.Richten Sie zunächst einen Testfall mit Dateinamen und Leerzeichen ein:
(Bearbeiten Sie einige Verzeichnis- und / oder Dateinamen in
new
).Nun wollen wir eine Map erstellen: Hash -> Dateiname für jedes Verzeichnis und dann dazu verwenden
join
, Dateien mit demselben Hash abzugleichen. Geben Sie Folgendes ein, um die Karte zu generierenmakemap.sh
:makemap.sh
spuckt eine Datei mit Zeilen der Form 'hash "filename"' aus, also fügen wir einfach die erste Spalte hinzu:Das erzeugt
moves.txt
was so aussieht:Der nächste Schritt wäre, die Züge tatsächlich zu machen, aber meine Versuche blieben beim Zitieren hängen ...
mv -i
undmkdir -p
sollten sich als nützlich erweisen.quelle
join
ist wirklich interessant. Vielen Dank, dass Sie mich darauf aufmerksam gemacht haben.join
Eingabe verwenden, nicht sortieren ?Es gibt ein Hilfsprogramm namens unison:
http://www.cis.upenn.edu/~bcpierce/unison/
Beschreibung vom Standort:
Beachten Sie, dass Unison verschobene Dateien bei der ersten Ausführung nur erkennt, wenn mindestens einer der Stammordner remote ist. Verwenden Sie ihn daher auch dann
ssh://localhost/path/to/dir
als einen der Stammordner, wenn Sie lokale Dateien synchronisieren .quelle
Verwenden Sie Unison wie von hasen j vorgeschlagen . Ich lasse diese Antwort als potenziell nützliches Skriptbeispiel oder zur Verwendung auf einem Server mit nur installierten Basisdienstprogrammen offen.
Ich gehe davon aus, dass die Dateinamen in der gesamten Hierarchie eindeutig sind. Ich gehe auch davon aus, dass kein Dateiname eine neue Zeile enthält und dass die Verzeichnisbäume nur Verzeichnisse und reguläre Dateien enthalten.
Sammeln Sie zuerst die Dateinamen auf der Quellseite.
Verschieben Sie dann die Dateien auf der Zielseite. Erstellen Sie zunächst einen abgeflachten Dateibaum auf der Zielseite. Verwenden Sie
ln
statt ,mv
wenn man hart Links um in der alten Hierarchie behalten will.Wenn im Ziel möglicherweise einige Dateien fehlen, erstellen Sie eine ähnlich reduzierte Datei
/A.staging
und kopieren Sie die Daten mit rsync von der Quelle zum Ziel.Benennen Sie nun die Dateien um.
Äquivalent:
Wenn Sie sich für die Metadaten der Verzeichnisse interessieren, rufen Sie schließlich rsync mit den bereits vorhandenen Dateien auf.
Beachten Sie, dass ich die Snippets in diesem Beitrag nicht getestet habe. Benutzung auf eigene Gefahr. Bitte melden Sie einen Fehler in einem Kommentar.
quelle
Insbesondere wenn eine fortlaufende Synchronisierung nützlich wäre, könnten Sie versuchen, den git-annex herauszufinden .
Es ist relativ neu; Ich habe nicht versucht, es selbst zu benutzen.
Ich kann es vorschlagen, da es vermeidet, eine zweite Kopie der Dateien zu behalten. Dies bedeutet, dass die Dateien als schreibgeschützt ("gesperrt") markiert werden müssen, wie dies bei bestimmten Versionskontrollsystemen ohne Git der Fall ist.
Dateien werden durch die Dateierweiterung sha256sum + (standardmäßig) identifiziert. Es sollte also in der Lage sein, zwei Repos mit identischem Dateiinhalt, aber unterschiedlichen Dateinamen zu synchronisieren, ohne dass Schreibvorgänge ausgeführt werden müssen (und, falls gewünscht, über ein Netzwerk mit geringer Bandbreite). Es muss natürlich alle Dateien lesen, um sie zu prüfen.
quelle
Wie wäre es mit so etwas:
Dies setzt voraus, dass die Namen der Dateien, die Sie synchronisieren möchten, auf dem gesamten Laufwerk eindeutig sind. Andernfalls ist eine vollständige Automatisierung nicht möglich.
Das obige Skript funktioniert in einfachen Fällen, kann jedoch fehlschlagen, wenn
name
Symbole enthalten sind, die für reguläre Ausdrücke eine besondere Bedeutung haben. Dasgrep
Auflisten von Dateien kann auch viel Zeit in Anspruch nehmen, wenn viele Dateien vorhanden sind. Sie können erwägen, diesen Code zu übersetzen, um eine Hash-Tabelle zu verwenden, die Dateinamen Pfaden zuordnet, z. B. in Ruby.quelle
grep
Leitung? Findet es nur den vollständigen Pfad der übereinstimmenden Datei indstlist
?ln
davon Symlinks. Sie könnenmv
die Dateien verschieben, achten Sie jedoch darauf, vorhandene Dateien nicht zu überschreiben. Möglicherweise möchten Sie auch leere Verzeichnisse bereinigen, nachdem Sie die Dateien entfernt haben. Ja, diesergrep
Befehl sucht nach einer Zeile, die auf dem Dateinamen endet, und gibt den vollständigen Pfad dazu auf dem Ziellaufwerk an.Angenommen, die Basisdateinamen sind in den Bäumen eindeutig, ist dies ziemlich einfach:
Wenn Sie die alten leeren Verzeichnisse bereinigen möchten, verwenden Sie:
quelle
Ich war auch mit diesem Problem konfrontiert. Die auf md5sum basierende Lösung hat bei mir nicht funktioniert, da ich meine Dateien mit einem
webdav
Mount synchronisiere . Das Berechnen von md5sum-Summen auf demwebdav
Ziel würde auch große Dateioperationen bedeuten.Ich habe ein kleines Skript
reorg_Remote_Dir_detect_moves.sh
(auf Github) erstellt, das versucht, die am meisten verschobenen Dateien zu erkennen , und dann ein neues temporäres Shell-Skript mit mehreren Befehlen zum Anpassen des Remote-Verzeichnisses erstellt. Da ich mich nur um die Dateinamen kümmere, ist das Skript keine perfekte Lösung.Aus Sicherheitsgründen werden mehrere Dateien ignoriert: A) Dateien mit demselben (gleichen Anfangs) Namen auf jeder Seite und B) Dateien, die sich nur auf der Remote-Seite befinden. Sie werden ignoriert und übersprungen.
Übersprungene Dateien werden dann von Ihrem bevorzugten Synchronisierungstool (z. B.
rsync, unison
...) verarbeitet, das Sie nach dem Ausführen des temporären Shell-Skripts verwenden müssen.Vielleicht ist mein Skript für jemanden nützlich? Wenn ja (um es klarer zu machen), gibt es drei Schritte:
reorg_Remote_Dir_detect_moves.sh
(auf Github)/dev/shm/REORGRemoteMoveScript.sh
=> führe dies aus, um die Bewegungen auszuführen (wird beim Mounten schnell ausgeführtwebdav
)rsync, unison
...)quelle
Hier ist mein Versuch einer Antwort. Als Warnung stamme meine gesamte Skripterfahrung aus Bash. Wenn Sie also eine andere Shell verwenden, können die Befehlsnamen oder die Syntax abweichen.
Diese Lösung erfordert das Erstellen von zwei separaten Skripten.
Dieses erste Skript ist für das Verschieben der Dateien auf dem Ziellaufwerk verantwortlich.
Das zweite Skript erstellt die vom ersten Skript verwendete MD5-Zuordnungsdatei und ruft dann das erste Skript für jede Datei auf dem Ziellaufwerk auf.
Im Grunde genommen simulieren die beiden Skripte ein assoziatives Array mit
$md5_map_file
. Zunächst werden alle MD5s für die Dateien auf dem Quelllaufwerk berechnet und gespeichert. Zu den MD5s gehören die relativen Pfade vom Stammverzeichnis des Laufwerks. Dann wird für jede Datei auf dem Ziellaufwerk der MD5 berechnet. Mit diesem md5 wird der Pfad dieser Datei auf dem Quelllaufwerk gesucht. Die Datei auf dem Ziellaufwerk wird dann so verschoben, dass sie mit dem Pfad der Datei auf dem Quelllaufwerk übereinstimmt.Mit diesem Skript sind einige Einschränkungen verbunden:
quelle
md5sum
scheint hier nicht das Richtige zu sein. (Übrigens, esrsync
gibt einen Modus, in dem keine Prüfsummen berechnet werden.)