cp-Befehl: Dateiordner in *nix korrekt kopieren

cp-Befehl: Dateiordner in *nix korrekt kopieren

In diesem Artikel werden einige nicht offensichtliche Dinge im Zusammenhang mit der Verwendung von enthüllt Platzhalter Beim Kopieren mehrdeutiges Befehlsverhalten cp beim Kopieren sowie Methoden, mit denen Sie eine große Anzahl von Dateien korrekt kopieren können, ohne dass es zu Sprüngen oder Abstürzen kommt.

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

Das erste, was mir in den Sinn kommt, ist:

cp /source/* /target

Korrigieren wir diesen Befehl sofort wie folgt:

cp -a /source/* /target

Schlüssel -a fügt das Kopieren aller Attribute und Rechte hinzu und fügt Rekursion hinzu. Wenn keine exakte Reproduktion der Rechte erforderlich ist, reicht ein Schlüssel aus -r.

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

.profile
.local
.mc

und dergleichen.

Warum ist das passiert?

Da Platzhalter von der Shell verarbeitet werden (bash im typischen Fall). Standardmäßig ignoriert Bash alle Dateien, die mit einem Punkt beginnen, da es sie als versteckt behandelt. Um dieses Verhalten zu vermeiden, müssen wir unser Verhalten ändern bash mit dem Befehl:

shopt -s dotglob

Um sicherzustellen, dass diese Verhaltensänderung nach einem Neustart bestehen bleibt, können Sie mit diesem Befehl im Ordner eine wildcard.sh-Datei erstellen /etc/profile.d (Vielleicht hat Ihre Distribution einen anderen Ordner).

Und wenn im Quellverzeichnis keine Dateien vorhanden sind, kann die Shell den Stern durch nichts ersetzen und auch das Kopieren schlägt mit einem Fehler fehl. Es gibt Optionen gegen diese Situation failglob и nullglob. Wir müssen einstellen failglob, wodurch verhindert wird, dass der Befehl ausgeführt wird. nullglob wird nicht funktionieren, da es einen String mit Platzhaltern, der keine Übereinstimmung gefunden hat, in einen leeren String (Null-Länge) konvertiert, was z cp wird einen Fehler verursachen.

Befinden sich jedoch Tausende oder mehr Dateien im Ordner, sollte auf den Platzhalter-Ansatz ganz verzichtet werden. Die Sache ist die bash erweitert Platzhalter zu einer sehr langen Befehlszeile wie:

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

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

getconf ARG_MAX

Lassen Sie uns die maximale Länge der Befehlszeile in Bytes ermitteln:

2097152

Или:

xargs --show-limits

Wir bekommen so etwas wie:

….
Maximum length of command we could actually use: 2089314
….

Verzichten wir also ganz auf Wildcards.

Lass uns einfach schreiben

cp -a /source /target

Und hier stehen wir vor einer Mehrdeutigkeit des Verhaltens cp. Wenn der Ordner /target nicht existiert, erhalten wir, was wir brauchen.

Wenn der Zielordner jedoch vorhanden ist, werden die Dateien in den Ordner /target/source kopiert.

Wir können den Ordner /target nicht immer im Voraus löschen, da er möglicherweise benötigte Dateien enthält und unser Ziel beispielsweise darin besteht, die Dateien in /target durch Dateien aus /source zu ergänzen.

Wenn der Quell- und der Zielordner denselben Namen hätten, wir würden beispielsweise von /source nach /home/source kopieren, könnten wir den folgenden Befehl verwenden:

cp -a /source /home

Und nach dem Kopieren würden die Dateien in /home/source durch Dateien aus /source ergänzt.

Dies ist ein logisches Problem: Wir können Dateien im Zielverzeichnis hinzufügen, wenn die Ordner den gleichen Namen haben. Wenn sie jedoch unterschiedlich sind, wird der Quellordner im Zielverzeichnis abgelegt. Wie kopiere ich Dateien mit cp ohne Platzhalter von /source nach /target?

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

cp -a /source/. /target

Wer sich mit DOS und Linux auskennt, hat bereits alles verstanden: In jedem Ordner befinden sich 2 unsichtbare Ordner „.“ und „..“, bei denen es sich um Pseudo-Ordner-Links zum aktuellen und höheren Verzeichnis handelt.

  • Beim Kopieren cp prüft die Existenz und versucht, /target/ zu erstellen.
  • Ein solches Verzeichnis existiert und es ist /target
  • Dateien von /source werden korrekt nach /target kopiert.

Hängen Sie es also in einem fetten Rahmen in Erinnerung oder an die Wand:

cp -a /source/. /target

Das Verhalten dieses Befehls ist klar. Alles funktioniert fehlerfrei, egal ob Sie eine Million Dateien haben oder gar keine.

Befund

Wenn Sie kopieren müssen alle Um Dateien von einem Ordner in einen anderen zu verschieben, verwenden wir keine Platzhalter, es ist besser, sie stattdessen zu verwenden cp kombiniert mit einem Punkt am Ende des Quellordners. Dadurch werden alle Dateien kopiert, auch die versteckten, und es wird nicht fehlschlagen, wenn es sich um Millionen oder gar keine Dateien handelt.

Nachwort

vmspike schlug eine Befehlsversion mit einem ähnlichen Ergebnis vor:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

HINWEIS: Briefkasten T hat die Bedeutung. Wenn Sie es verwechseln, erhalten Sie völligen Müll: Die Kopierrichtung ändert sich.
Vielen Dank:

  • Firmen RUVDS.COM für Ihre Unterstützung und die Möglichkeit, in Ihrem Blog auf Habré zu veröffentlichen.
  • Pro Bild Dreifaches Konzept. Das Bild ist sehr groß und detailliert, kann in einem separaten Fenster geöffnet werden.

PS Bitte senden Sie alle Fehler, die Ihnen auffallen, in einer privaten Nachricht. Dafür erhöhe ich mein Karma.

cp-Befehl: Dateiordner in *nix korrekt kopieren

Source: habr.com

Kommentar hinzufügen