Das cp-Team: korrektes Kopieren von Ordnern mit Dateien in *nix

Das cp-Team: korrektes Kopieren von Ordnern mit Dateien in *nix

In diesem Artikel werden einige offensichtliche Dinge im Zusammenhang mit der Nutzung wildcards beim Kopieren, das mehrdeutige Verhalten des Befehls cp beim Kopieren sowie Methoden, die es ermöglichen, eine große Anzahl von Dateien ohne Auslassungen und Abstürze korrekt zu kopieren.

Angenommen, wir müssen alles aus dem Ordner /source in den Ordner /target kopieren.

Das Erste, was mir einfällt, ist:

cp /source/* /target

Lassen Sie uns diesen Befehl sofort auf Folgendes korrigieren:

cp -a /source/* /target

Schlüssel -a fügt das Kopieren aller Attribute und Rechte hinzu und aktiviert die Rekursion. Wenn eine genaue Wiederherstellung der Rechte nicht erforderlich ist, genügt der Schlüssel -r.

Nach dem Kopieren stellen wir fest, dass nicht alle Dateien kopiert wurden – Dateien, die mit einem Punkt beginnen, wurden ignoriert, wie zum Beispiel:

.profil
.lokal
.mc

und ähnliches.

Warum ist das passiert?

Weil Wildcards vom Shell verarbeitet werden (bash im typischen Fall). Standardmäßig ignoriert Bash alle Dateien, die mit Punkten beginnen, da sie als versteckt betrachtet werden. Um dieses Verhalten zu vermeiden, müssen wir das Verhalten ändern bash mit dem Befehl:

shopt -s dotglob

Damit diese Verhaltensänderung nach einem Neustart bestehen bleibt, können wir eine Datei wildcard.sh mit diesem Befehl im Ordner erstellen /etc/profile.d (vielleicht gibt es in Ihrer Distribution einen anderen Ordner).

Wenn im Quellverzeichnis jedoch keine Dateien vorhanden sind, kann das Shell nichts anstelle des Sternchens einsetzen, und das Kopieren endet ebenfalls mit einem Fehler. Gegen eine solche Situation gibt es Optionen failglob und nullglob. Wir müssen einstellen failglob, die dazu führen wird, dass der Befehl nicht ausgeführt werden kann. nullglob funktioniert nicht, da sie die Zeile mit nicht übereinstimmenden Wildcards in eine leere Zeichenfolge (Nulllänge) umwandelt, was für cp einen Fehler verursachen wird.

Wenn jedoch im Ordner Tausende von Dateien und mehr vorhanden sind, sollte man vollständig auf den Ansatz mit Wildcards verzichten. Der Grund ist, dass bash Wildcards in eine sehr lange Befehlszeile wie folgt entfaltet:

cp -a /souce/a /source/b /source/c …… /target

Es gibt eine Begrenzung für die Länge der Befehlszeile, die wir mit dem Befehl herausfinden können:

getconf ARG_MAX

Wir erhalten die maximale Länge der verwendbaren Befehlszeile in Bytes:

2097152

Oder:

xargs --show-limits

Wir erhalten etwas wie:

….
Maximale Länge des Befehls, den wir tatsächlich verwenden können: 2089314
….

Also lassen Sie uns vollständig auf Wildcards verzichten.

Lassen Sie uns einfach schreiben

cp -a /source /target

Und hier stoßen wir auf die Mehrdeutigkeit des Verhaltens cp. Wenn der Ordner /target nicht existiert, erhalten wir, was wir brauchen.

Wenn der Ordner target jedoch existiert, werden die Dateien in den Ordner /target/source kopiert.

Nicht immer können wir im Voraus den Ordner /target löschen, da darin möglicherweise benötigte Dateien enthalten sind, und unser Ziel könnte zum Beispiel sein, die Dateien in /target mit Dateien aus /source zu ergänzen.

Wenn der Quell- und der Zielordner denselben Namen hätten, zum Beispiel, wenn wir von /source nach /home/source kopieren würden, könnte man den Befehl verwenden:

cp -a /source /home

Und nach dem Kopieren wären die Dateien in /home/source mit Dateien aus /source ergänzt worden.

So eine logische Aufgabe: Wir können die Dateien im Zielverzeichnis ergänzen, wenn die Ordner denselben Namen haben, aber wenn sie unterschiedlich sind, wird der Quellordner im Zielordner abgelegt. Wie kopiert man Dateien von /source nach /target mit cp ohne Wildcards?

Um diese schädliche Einschränkung zu umgehen, verwenden wir eine unerwartete Lösung:

cp -a /source/. /target

Diejenigen, die sich gut mit DOS und Linux auskennen, haben bereits alles verstanden: In jedem Ordner gibt es 2 unsichtbare Ordner „.“ und „..“, die spezielle Links auf das aktuelle und das übergeordnete Verzeichnis sind.

  • Beim Kopieren cp überprüft es die Existenz und versucht, /target/ zu erstellen.
  • Ein solches Verzeichnis existiert bereits und das ist /target
  • Die Dateien aus /source wurden korrekt in /target kopiert.

Also hängen wir uns das in fetten Rahmen in unser Gedächtnis oder an die Wand:

cp -a /source/. /target

Das Verhalten dieses Befehls ist eindeutig. Alles wird fehlerfrei funktionieren, unabhängig davon, ob Sie eine Million Dateien haben oder keine.

Das DBMS Tarantool ist ein attraktives, zukunftsträchtiges Produkt zur Erstellung von hochbelasteten Anwendungen.

Wenn Sie Dateien Ressourcen) abgeschlossen ist, lösen wir von einem Ordner in einen anderen kopieren müssen, verwenden Sie keine Wildcards; stattdessen sollten Sie cp in Kombination mit einem Punkt am Ende des Quellordners verwenden. Das wird alle Dateien, einschließlich versteckter, kopieren und wird bei Millionen von Dateien oder beim völligen Fehlen von Dateien nicht abstürzen.

Nachwort

vmspike schlug eine ähnliche Befehlsvariante vor:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

ACHTUNG: Die Groß- und Kleinschreibung T ist wichtig. Wenn Sie das verwechseln, bekommen Sie ein völliges Durcheinander: Die Kopierrichtung ändert sich.
Danksagungen:

  • Unternehmen RUVDS.COM für die Unterstützung und Möglichkeit zur Veröffentlichung in meinem Blog auf Habr.
  • Für das Bild TripletConcept. Das Bild ist sehr groß und detailliert, man kann es in einem separaten Fenster öffnen.

P.S. Bitte Fehler per privater Nachricht melden. Ich erhöhe dafür die Karma.

Das cp-Team: korrektes Kopieren von Ordnern mit Dateien in *nix

Quelle: habr.com

60GB SSD 8Gb DDR4