
In diesem Artikel werden einige weniger offensichtliche Aspekte der Verwendung von beim Kopieren, das unvorhersehbare Verhalten des cp Kopierbefehls sowie Methoden, die es ermöglichen, eine große Anzahl von Dateien ohne Überspringen oder Abbrüche korrekt zu kopieren, erläutert.
Angenommen, wir müssen alles aus dem Ordner /source in den Ordner /target kopieren.
Das Erste, was einem in den Sinn kommt, ist:
cp /source/* /targetWir werden diesen Befehl sofort korrigieren zu:
cp -a /source/* /target Der Schlüssel -a Dies fügt das Kopieren aller Attribute, Berechtigungen hinzu und aktiviert die Rekursion. Wenn eine exakte Wiederherstellung der Berechtigungen nicht erforderlich ist, reicht der Schalter -r.
Nach dem Kopieren stellen wir fest, dass nicht alle Dateien kopiert wurden – Dateien, die mit einem Punkt beginnen, wurden ignoriert, wie z.B.:
.profil
.lokal
.mc
und ähnliche.
Warum ist das passiert?
Weil Wildcards vom Shell verarbeitet werden (bash im Standardfall). Standardmäßig ignoriert Bash alle Dateien, die mit einem Punkt beginnen, da es sie als versteckt interpretiert. Um dieses Verhalten zu ändern, müssen wir bash den Befehl verwenden:
shopt -s dotglob Um dieses Verhaltensänderung nach einem Neustart beizubehalten, kann eine Datei wildcard.sh mit diesem Befehl im Ordner erstellt werden. /etc/profile.d (möglicherweise gibt es in Ihrer Distribution einen anderen Ordner).
Wenn im Quellverzeichnis keine Dateien vorhanden sind, kann die Shell nichts anstelle des Sternchens einsetzen, und das Kopieren endet ebenfalls mit einem Fehler. Für solche Situationen gibt es die Optionen failglob und nullglob. Wir müssen festlegen failglob, die den Befehl davon abhalten wird, ausgeführt zu werden. nullglob ist nicht geeignet, da sie eine Zeile mit Wildcards, die keine Übereinstimmungen gefunden haben, in eine leere Zeile (nulllängige) umwandelt, was zu cp einem Fehler führt.
Wenn es jedoch tausende von Dateien im Ordner gibt, sollten wir ganz auf die Verwendung von Wildcards verzichten. Der Grund dafür ist, dass bash Wildcards in eine sehr lange Befehlszeile umwandelt, wie zum Beispiel:
cp -a /souce/a /source/b /source/c …… /targetEs gibt eine Begrenzung für die Länge der Befehlszeile, die wir mit dem Befehl herausfinden können:
getconf ARG_MAXWir erhalten die maximale Länge der Befehlszeile in Byte:
2097152Oder:
xargs --show-limitsWir erhalten etwas wie:
….
Maximale Länge des Befehls, den wir tatsächlich verwenden könnten: 2089314
….Also, lassen Sie uns ganz auf Wildcards verzichten.
Lassen Sie uns einfach schreiben
cp -a /source /target Und hier stoßen wir auf Mehrdeutigkeit im Verhalten cp. Wenn der Ordner /target nicht existiert, erhalten wir genau das, was wir brauchen.
Wenn der Zielordner jedoch existiert, werden die Dateien in den Ordner /target/source kopiert.
Wir können den Ordner /target nicht immer im Voraus löschen, da dort möglicherweise benötigte Dateien sind. Unser Ziel ist es, beispielsweise die Dateien im Ordner /target mit denen aus /source zu ergänzen.
Wenn die Quell- und 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 /homeNach dem Kopieren wären die Dateien in /home/source mit den Dateien aus /source ergänzt.
Hier ist eine logische Herausforderung: Wir können die Dateien im Zielverzeichnis ergänzen, wenn die Ordner denselben Namen tragen. Wenn sie unterschiedlich sind, wird der Quellordner im Zielort platziert. Wie kopiere ich die Dateien von /source nach /target mit cp ohne Wildcards?
Um dieses schädliche Limit zu umgehen, verwenden wir eine unerwartete Lösung:
cp -a /source/. /targetDiejenigen, die sich gut mit DOS und Linux auskennen, haben es bereits verstanden: In jedem Ordner gibt es zwei unsichtbare Ordner „.“ und „..“, die als pseudo-Ordner auf das aktuelle sowie das übergeordnete Verzeichnis verweisen.
- Beim Kopieren
cpüberprüft das Programm die Existenz und versucht, /target/ zu erstellen. - Ein solches Verzeichnis existiert und das ist /target.
- Die Dateien aus /source wurden korrekt in /target kopiert.
Also, merken Sie sich dies gut oder hängen Sie es an die Wand:
cp -a /source/. /target
Das Verhalten dieses Befehls ist eindeutig. Alles wird fehlerfrei ausgeführt, unabhängig davon, ob Sie Millionen von Dateien oder gar keine haben.
Fazit
Wenn Sie Dateien alle von einem Ordner in einen anderen kopieren müssen, verwenden Sie keine Wildcards; stattdessen ist es besser, cp in Kombination mit einem Punkt am Ende des Quellordners zu verwenden. Das kopiert alle Dateien, einschließlich versteckter, und bricht nicht bei Millionen von Dateien oder völliger Abwesenheit von Dateien zusammen.
Nachwort
schlug eine ähnliche Befehlsvariante vor:
cp -a -T /source /target
cp -aT /source /target ACHTUNG: Groß- und Kleinschreibung T spielt eine Rolle. Wenn Sie es verwechseln, erhalten Sie kompletten Unsinn: Die Kopierrichtung wird gewechselt.
Danksagungen:
- Firmen für die Unterstützung und die Möglichkeit, in ihrem Blog auf Habr zu veröffentlichen.
- Für das Bild . Das Bild ist sehr groß und detailliert, kann in einem separaten Fenster geöffnet werden.
P.S. Bitte sendet entdeckte Fehler privat. Ich erhöhe dafür die Karma.
Quelle: habr.com
