Hier ist der wichtige Teil aus der Manpage:
Während die Liste der zu übertragenden Dateien/Verzeichnisse erstellt wird, prüft rsync nacheinander jeden zu übertragenden Namen mit der Liste der Einschluss-/Ausschlussmuster, und das erste übereinstimmende Muster wird bearbeitet:Wenn es ein Ausschlussmuster ist, dann ist es diese Datei übersprungen; wenn es sich um ein Include-Muster handelt, wird dieser Dateiname nicht übersprungen; wenn kein übereinstimmendes Muster gefunden wird, wird der Dateiname nicht übersprungen.
Zusammenfassend:
- Wenn kein Muster übereinstimmt, wird eine Datei kopiert!
- Der Algorithmus wird beendet, sobald ein Muster übereinstimmt
Außerdem stimmt etwas, das mit einem Schrägstrich endet, mit Verzeichnissen überein (wie find -type d
würde).
Ziehen wir diese Antwort von oben auseinander.
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"
- Keine Verzeichnisse überspringen
- Überspringen Sie keine
.sh
Dateien - Alles überspringen
- (Überspringen Sie implizit nichts, aber die obige Regel verhindert, dass die Standardregel jemals eintritt.)
Schließlich die --prune-empty-directories
verhindert, dass die erste Regel überall leere Verzeichnisse erstellt.
Ich denke --include
wird verwendet, um eine Teilmenge von Dateien einzuschließen, die ansonsten durch --exclude
ausgeschlossen werden , anstatt nur diese Dateien einzubinden. Mit anderen Worten:Sie müssen über Einschließen nachdenken bedeutet nicht ausschließen .
Versuchen Sie stattdessen:
rsync -zarv --include "*/" --exclude="*" --include="*.sh" "$from" "$to"
Für rsync-Version 3.0.6 oder höher muss die Reihenfolge wie folgt geändert werden (siehe Kommentare):
rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"
Hinzufügen des -m
-Flag vermeidet das Erstellen leerer Verzeichnisstrukturen im Ziel. Getestet in Version 3.1.2.
Wenn wir also nur *.sh-Dateien wollen, müssen wir alle Dateien ausschließen --exclude="*"
, enthalten alle Verzeichnisse --include="*/"
und alle *.sh-Dateien einschließen --include="*.sh"
.
Einige gute Beispiele finden Sie im Abschnitt Musterregeln einschließen/ausschließen der Manpage
Eine weitere Ergänzung:Wenn Sie Dateien anhand ihrer Erweiterungen in nur einem Verzeichnis synchronisieren müssen (ohne Rekursion) sollten Sie eine Konstruktion wie diese verwenden:
rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/
Achten Sie auf den Punkt im ersten --include
. --no-r
funktioniert in dieser Konstruktion nicht.
BEARBEITEN:
Danke an gbyte.co für den wertvollen Kommentar!
BEARBEITEN:
Die -uzv
Flags beziehen sich nicht direkt auf diese Frage, aber ich habe sie eingefügt, weil ich sie normalerweise verwende.
Die Antwort von @chepner kopiert alle Unterverzeichnisse, unabhängig davon, ob sie Dateien enthalten oder nicht. Wenn Sie die Unterverzeichnisse ausschließen müssen, die die Datei nicht enthalten, und dennoch die Verzeichnisstruktur beibehalten möchten, verwenden Sie
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"