Ändern von zsh-Globbing-Mustern zur Verwendung mit cp

Ändern von zsh-Globbing-Mustern zur Verwendung mit cp

Ich versuche, ein Skript zu schreiben, um Dateien rekursiv aus einem bestimmten Ordner zu kopieren, außer files A.extn, B/*.extnund C/*wobei Bund CVerzeichnisse sind und extnnur eine generische Erweiterung ist. Das habe ich:

#!/usr/local/bin/zsh
setopt EXTENDED_GLOB
TMPDIR=/tmp/test

cp -pR $(dirname $0)/**~(*.foo/*|*/bar.txt|*.abc|qux.txt) $TMPDIR

Dies führt jedoch nicht wie erwartet zur Negierung des Musters. Ich glaube, ich weiß, warum – obwohl das Muster korrekt ist (wie bei zu sehen echo), cp -Rist sich das Muster nicht bewusst und betritt ein Verzeichnis, in das es „nicht gehört“, und sobald es dort ist, ist das Muster nicht mehr gültig.

Wie ändere ich das Obige, um das zu erreichen, was ich will? Ich denke, es ist mit findund möglich xargs, aber ich bin von der Klarheit des Obigen angetan und würde etwas Ähnliches bevorzugen (wenn es aber die falsche Vorgehensweise ist, wäre ich mit einer anderen Lösung vollkommen zufrieden).

Antwort1

Sie haben Recht, dass das Muster vor der Ausführung erweitert wird cpund daher diesem Befehl unbekannt ist.

Möglicherweise können Sie Ihr Ziel erreichen, indem Sie die --parentsOption to cpanstelle von verwenden -R. Dadurch werden nur die Dateien kopiert, die Ihrem Muster entsprechen, es wird jedoch der vollständige Pfadname wie angegeben verwendet und nicht nur der nachfolgende Dateiname.

Diese Option ist jedoch nicht portierbar. Soweit ich weiß, wird sie nur von der GNU-Version von cp unterstützt.

Antwort2

Ihr Muster schließt möglicherweise die Dateien aus, die Sie nicht kopieren möchten, aber es schließt nicht die Verzeichnisse aus, die diese enthalten und die Sie angewiesen haben, cprekursiv zu kopieren. Die Dateien werden also trotzdem kopiert. Schlimmer noch, wenn Sie einen Quellbaum wie

foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt

Anschließend wird das Muster erweitert, foo hello hello/world hello/world/wibble.txtsodass Sie am Ende folgende Dateien erhalten $TMPDIR:

foo
foo/bar.txt
hello
hello/world
hello/world/wibble.txt
wibble.txt
world
world/wibble.txt

Dies hat nichts damit zu tun, dass das Muster „nicht mehr gültig“ ist. Das Muster wird von der Shell erweitert und cpsieht nur die Liste der Dateien.

Sie müssen ein Kopiertool verwenden, das Dateien ausschließen kann, während es die rekursive Durchquerung durchführt.

Sie können hierfür zcp verwenden, es kopiert die Verzeichnisse jedoch nicht und erstellt auch keine Zielverzeichnisse automatisch. Das einfachste Tool für diese Aufgabe ist rsync. Pax ist eine weitere Option.

rsync -a --exclude='*.foo/*' --exclude='bar.txt' --exclude='*.abc' --exclude='/qux.txt' $(dirname $0) $TMPDIR

verwandte Informationen