Bash kopiert Dateien aus mehreren Verzeichnissen in mehrere entsprechende Sicherungsverzeichnisse

Bash kopiert Dateien aus mehreren Verzeichnissen in mehrere entsprechende Sicherungsverzeichnisse

Ich habe mehrere Verzeichnisse { dir1,dir2,dir3,dir4} auf einer Linux-Box.

In jedem Verzeichnis gibt es mehrere Dateien (mit derselben Erweiterung, sagen wir .zip), die ich in den entsprechenden Verzeichnissen { dir1-bck,dir2-bck,dir3-bck,dir4-bck} sichern möchte. Ich muss nicht den gesamten Ordner sichern, sondern nur ein paar Dateien in jedem.

dir1/*.zipWie kann ich die kopierten Dateien in ... ablegen dir1-bck? Eine Liste der bereitgestellten Verzeichnisse wird angezeigt. Ich verwende derzeit:

cp -r src/dir1/*.zip dest/dir1-bck/
cp -r src/dir2/*.zip dest/dir2-bck/
cp -r src/dir3/*.zip dest/dir3-bck/
cp -r src/dir4/*.zip dest/dir4-bck/

Das funktioniert, es besteht aber noch viel Raum für Verbesserungen.

Beim Durchsehen der xargsManpage und ähnlicher Beiträge im Forum habe ich das Gefühl, dass dies das richtige Tool für diese Aufgabe ist, aber ich scheine es nicht richtig hinzubekommen.

Antwort1

Wahrscheinlich forist eine Schleife genau das Richtige. Die genaue Form hängt davon ab, wie diese Verzeichnisse benannt sind. Sie kann lauten:

cd src || exit 1
for d in "dir"{1..4}; do
   cp -r "$d"/*.zip "../dest/$d-bck/"
done

Anmerkungen:

  • Es empfiehlt sich, innerhalb von src( cd src) zu arbeiten, damit die Variable eine Zeichenfolge enthält, die ohne zusätzliche Verarbeitung im Zielpfad verwendet werden kann. Der Zielpfad wurde ../in diesem Fall durch Voranstellen angepasst, aber im Allgemeinen kann er wie folgt aussehen "/full/path/to/dest/$d-bck/".
  • Ich habe Anführungszeichen gesetzt, dirfalls Sie einen Namen durch Leerzeichen oder ähnliches ersetzen. Ich habe $daus demselben Grund doppelte Anführungszeichen gesetzt undmehr.
  • Wenn *.zipes sich um Dateien handelt, brauchen Sie sie nicht -r.

Alternativ könnte die forZeile lauten:

for d in dir1 dir2 dir3 dir4; do

Dies wäre nützlich, wenn Sie einige beliebig benannte Verzeichnisse angeben müssen. Oder sogar:

for d in *; do

Es können einige Verbesserungen vorgenommen werden, wie diese:

( cd src || exit 1
for d in *; do
   dst="../dest/$d-bck/"
   [ -d "$d" ] && mkdir -p "$dst" && cp -- "$d"/*.zip "$dst"
done )

Die Verbesserungen:

  • Der gesamte Code wird in einer Subshell ( (…)) ausgeführt und hat daher cdkeine Auswirkungen auf die aktuelle Shell, selbst wenn Sie den Code in ein Terminal einfügen. Wenn es sich um ein eigenständiges Skript handeln müsste (ausgeführt, nicht als Quelle), wäre die Subshell irrelevant.
  • Wir prüfen, ob $des sich um ein Verzeichnis handelt.
  • Wir versuchen das Zielverzeichnis zu erstellen (falls es nicht existiert).
  • Wir fahren cpnur fort, wenn das Zielverzeichnis existiert.
  • Wir gebrauchenDoppelstrichfalls es $dmit einem Bindestrich beginnt.

Mögliche Probleme:

  • "$d"/*.zipkann sich auf zu viele Elemente erweitern ( Argument list too long). Ihre ursprünglichen Befehle sind auf die gleiche Weise „fehlerhaft“. Wenn sich „nur ein paar Dateien in jedem“ Verzeichnis befinden, sollte dies kein Problem sein.
  • "$d"/*.zipdarf nicht erweitert werden ( *bleibt wörtlich). Es sollte keinen Schaden anrichten, das Zielverzeichnis wird trotzdem vorher erstellt. In einem solchen Fall kann zusätzliche Logik erforderlich sein, um die Verzeichniserstellung zu unterdrücken.
  • Der Beendigungsstatus des gesamten Snippets hängt nur vom letzten ab [ … && mkdir … && cp …. Sie benötigen zusätzliche Logik, damit frühere Probleme den Beendigungsstatus beeinflussen.

verwandte Informationen