
In diesem Artikel werden einige nicht offensichtliche Aspekte im Zusammenhang mit der Verwendung von
Platzhaltern beim Kopieren, dem mehrdeutigen Verhalten des Befehls
cp
beim Kopieren sowie Möglichkeiten zum korrekten Kopieren einer großen Anzahl von Dateien ohne Auslassungen und Abstürze erläutert.
Angenommen, 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 Sie diesen Befehl sofort auf:
cp -a /source/* /target
Der Schalter
-a
fügt eine Kopie aller Attribute, Rechte und Rekursionen hinzu. Wenn keine genaue Wiedergabe von Rechten erforderlich ist, reicht der Schalter
-r
aus.
Nach dem Kopieren stellen wir fest, dass nicht alle Dateien kopiert wurden - Dateien ab einem Punkt wie wurden ignoriert:
.profile
.local
.mc
und dergleichen.
Warum ist das passiert?
Weil Platzhalter die Shell verarbeiten (
bash
in einem typischen Fall). Standardmäßig ignoriert bash alle Dateien, die mit Punkten beginnen, da sie als versteckt behandelt werden. Um dieses Verhalten zu vermeiden, müssen wir das Verhalten von
bash
mit dem folgenden Befehl ändern:
shopt -s dotglob
Um diese Verhaltensänderung nach einem Neustart zu speichern, können Sie die Datei wildcard.sh mit diesem Befehl im Ordner
/etc/profile.d
(Ihre Distribution hat möglicherweise einen anderen Ordner).
Wenn sich keine Dateien im Quellverzeichnis befinden, kann die Shell das Sternchen nicht ersetzen, und das Kopieren schlägt ebenfalls fehl. In dieser Situation gibt es
failglob
und
nullglob
. Wir müssen
failglob
, um zu verhindern, dass der Befehl ausgeführt wird.
nullglob
nicht, da es eine Zeichenfolge mit Platzhaltern, die keine Übereinstimmungen gefunden haben, in eine leere Zeichenfolge (mit der Länge Null) konvertiert, was einen Fehler für
cp
.
Wenn sich jedoch Tausende von Dateien und mehr im Ordner befinden, sollte der Ansatz mit Platzhaltern ganz aufgegeben werden. Die Sache ist,
bash
erweitert Platzhalter in eine sehr lange Befehlszeile wie:
cp -a /souce/a /source/b /source/c …… /target
Die Länge der Befehlszeile ist begrenzt, was wir mit dem Befehl herausfinden können:
getconf ARG_MAX
Ermitteln Sie die maximale Länge der Befehlszeile in Byte:
2097152
Oder:
xargs --show-limits
Wir bekommen so etwas wie:
…. Maximum length of command we could actually use: 2089314 ….
Lassen Sie uns also überhaupt auf Platzhalter verzichten.
Lass uns einfach schreiben
cp -a /source /target
Und hier werden wir auf die Mehrdeutigkeit des
cp
Verhaltens stoßen. Wenn der Ordner / target nicht vorhanden ist, erhalten wir das, was wir benötigen.
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 die benötigten Dateien enthält und unser Ziel beispielsweise darin besteht, / target Dateien mit Dateien aus / source hinzuzufügen.
Wenn der Quell- und der Zielordner beispielsweise auf dieselbe Weise benannt würden, würden wir von / source nach / home / source kopieren, dann könnten wir den folgenden Befehl verwenden:
cp -a /source /home
Und nach dem Kopieren der Dateien in / home / source wären die ergänzten Dateien aus / source.
Dies ist die logische Aufgabe: Wir können Dateien zum Zielverzeichnis hinzufügen. Wenn die Ordner den gleichen Namen haben, sich jedoch unterscheiden, wird der Quellordner im Empfänger abgelegt. Wie kopiere ich Dateien von / source nach / target mit cp ohne Platzhalter?
Um diese schädliche Einschränkung zu umgehen, verwenden wir eine nicht offensichtliche Lösung:
cp -a /source/. /target
Diejenigen, die mit DOS und Linux gut vertraut sind, haben bereits alles verstanden: In jedem Ordner befinden sich 2 unsichtbare Ordner "." und "..", die Pseudoordner-Links zu den aktuellen und höheren Verzeichnissen sind.
- Beim Kopieren prüft
cp
Existenz und versucht, / target / zu erstellen. - Ein solches Verzeichnis existiert und es ist / target
- Dateien von / source wurden korrekt nach / target kopiert.
Also hängen wir in einem kühnen Rahmen in unserer Erinnerung oder an der Wand:
cp -a /source/. /target
Das Verhalten dieses Befehls ist eindeutig. Alles funktioniert fehlerfrei, unabhängig davon, ob Sie eine Million oder gar keine Dateien haben.
Schlussfolgerungen
Wenn Sie
alle Dateien von einem Ordner in einen anderen kopieren möchten, verwenden wir keine Platzhalter. Stattdessen ist es besser,
cp
in Kombination mit einem Punkt am Ende des Quellordners zu verwenden. Dies kopiert alle Dateien, einschließlich versteckter, und schlägt nicht mit Millionen von Dateien oder dem völligen Fehlen von Dateien fehl.
Nachwort
vmspike schlug eine ähnliche Variante des Befehls vor:
cp -a -T /source /target
Oz_Alex cp -aT /source /target
ACHTUNG: Der Fall des Buchstabens
T
wichtig. Wenn Sie es verwechseln, erhalten Sie den kompletten Müll: Die Kopierrichtung ändert sich.
Danksagung:
- RUVDS.COM Unternehmen für seine Unterstützung und die Möglichkeit, auf seinem Blog auf Habré zu veröffentlichen.
- Pro Bild TripletConcept . Das Bild ist sehr groß und detailliert, Sie können es in einem separaten Fenster öffnen.
PS Direkte Fehler, die Sie in PM bemerken. Ich erhöhe das Karma dafür.
