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/*.zip
Wie 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 xargs
Manpage 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 for
ist 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,
dir
falls Sie einen Namen durch Leerzeichen oder ähnliches ersetzen. Ich habe$d
aus demselben Grund doppelte Anführungszeichen gesetzt undmehr. - Wenn
*.zip
es sich um Dateien handelt, brauchen Sie sie nicht-r
.
Alternativ könnte die for
Zeile 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 dahercd
keine 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
$d
es sich um ein Verzeichnis handelt. - Wir versuchen das Zielverzeichnis zu erstellen (falls es nicht existiert).
- Wir fahren
cp
nur fort, wenn das Zielverzeichnis existiert. - Wir gebrauchenDoppelstrichfalls es
$d
mit einem Bindestrich beginnt.
Mögliche Probleme:
"$d"/*.zip
kann 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"/*.zip
darf 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.