rsync kopiert nur bestimmte Dateitypen mit der Option include

110

Ich verwende das folgende Bash-Skript, um nur Dateien mit einer bestimmten Erweiterung (in diesem Fall * .sh) zu kopieren, es kopiert jedoch immer noch alle Dateien. Was ist los mit dir?

von = $ 1
bis = $ 2

rsync -zarv --include = "*. sh" $ von $ bis
user881480
quelle
4
Obwohl dies nicht streng verwandt ist, würde ich vorschlagen, $ from / $ to zu zitieren. Wenn Sie dies nicht tun, erhalten Sie möglicherweise unerwartete Ergebnisse, wenn die Positionsargumente 1/2 Leerzeichen enthalten.
Kjetil Joergensen
Hast du verstanden, warum dein Befehl nicht einfach funktioniert?
Charlie Parker
@CharlieParker: Müssen Sie verwenden rsync, dies kann sehr gut mit den Shell-Interna erreicht werden?
Inian
Was dieser Frage und ihren Antworten auch fehlt, ist, wie der Befehl erstellt wird, wenn ich rekursive Verzeichnisse habe, für die ich nur einen Dateityp senden möchte. Es scheint, dass es nur für das Zielverzeichnis tut ...
Charlie Parker

Antworten:

198

Ich denke, --includewird verwendet, um eine Teilmenge von Dateien einzuschließen, die ansonsten von ausgeschlossen werden --exclude, anstatt nur diese Dateien einzuschließen. Mit anderen Worten: Sie müssen über die Einschlussbedeutung nachdenken, die Sie 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"

Durch Hinzufügen des -mFlags wird vermieden, dass leere Verzeichnisstrukturen im Ziel erstellt werden. Getestet in Version 3.1.2.

Wenn wir also nur * .sh-Dateien wollen, müssen wir alle Dateien ausschließen --exclude="*", alle Verzeichnisse --include="*/"einschließen und alle * .sh-Dateien einschließen --include="*.sh".

Einige gute Beispiele finden Sie im Abschnitt Musterregeln ein- / ausschließen der Manpage

chepner
quelle
10
Sie erhalten zwar alle Unterverzeichnisse, aber wenn sich in den Unterverzeichnissen, die Sie synchronisieren möchten, .sh-Dateien befinden, möchten Sie wahrscheinlich auch --include = "* /" verwenden.
Kjetil Joergensen
50
Ich habe dies auf rsync Version 3.0.7 versucht, die ich vor langer Zeit von macports erhalten habe, und es hat mit dieser Reihenfolge von Einschlüssen / Ausschlüssen nicht funktioniert. Dies ist, was ich am Ende für mich gearbeitet habe (angepasst für OP) : rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to".
Bijou Trouvaille
3
Ich habe es mit rsync 3.0.9 versucht und es hat nicht funktioniert. Bijou hat recht, die Bestellung ist nicht richtig (erst --include=\*.shdann --exclude=\*)
TrueY
3
Beachten Sie, dass Sie jederzeit auf Bearbeiten klicken und die Antwort bearbeiten können :)
Achal Dave
2
Es funktioniert nicht mit Ihrer Bestellung von Includes / Exludes, aber es funktioniert mit der von Bijou Trouvaille vorgeschlagenen Bestellung
John Smith Optional
56

Die Antwort von @chepner kopiert alle Unterverzeichnisse, unabhängig davon, ob sie die Datei enthalten oder nicht. Wenn Sie die Unterverzeichnisse ausschließen müssen, die die Datei nicht enthalten und dennoch die Verzeichnisstruktur beibehalten, verwenden Sie

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
WanderingMind
quelle
1
Dies war eine Voraussetzung für mich: "Wenn Sie die Unterverzeichnisse ausschließen müssen, die die Datei nicht enthalten und dennoch die Verzeichnisstruktur beibehalten" +1
Juuso Ohtonen
1
Ich verstehe nicht, woher wusstest du, wie die Reihenfolge der Einschlüsse war?
Charlie Parker
1
Wie erstellt man den Befehl, wenn ich rekursive Verzeichnisse habe, die ich nur einen Dateityp senden möchte? Es scheint, dass dies nur für das Zielverzeichnis gilt.
Charlie Parker
15

Noch eine Ergänzung: Wenn Sie Dateien anhand ihrer Erweiterungen nur in einem Verzeichnis (ohne Rekursion) synchronisieren müssen, sollten Sie eine Konstruktion wie die folgende verwenden:

rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/

Achten Sie auf den Punkt im ersten --include.--no-rfunktioniert in dieser Konstruktion nicht.

BEARBEITEN:

Vielen Dank an gbyte.co für den wertvollen Kommentar!

Serge Roussak
quelle
1
Woher wussten Sie, wie die Reihenfolge der Flaggen lauten musste und was sie enthalten mussten?
Charlie Parker
1
@CharlieParker, da der rsync die includeund die excludeOptionen in der Reihenfolge verwendet, in der sie angegeben wurden. Außerdem wird der erste übereinstimmende angehalten. Wenn wir also --exclude '*'in diesem Beispiel an erster Stelle das angeben, wird rsync nichts tun. Siehe den Mann für weitere Erklärungen.
Serge Roussak
Kannst du mir erklären, was jede Flagge tut? Das erste Flag -- include './' lautet: Alles in den Quellverzeichnispfad aufnehmen? Dann schließt das nächste `--include '.ext'` die spezifische Datei in den genannten Quellpfad ein .extund dann sagt das exclude, dass Sie nichts anderes senden --exclude '*'? Ist das korrekt?
Charlie Parker
1
Wie erstellt man den Befehl, wenn ich rekursive Verzeichnisse habe, die ich nur einen Dateityp senden möchte? Es scheint, dass dies nur für das Zielverzeichnis gilt.
Charlie Parker
1
Danke dafür! Bedürfnisse --include '*.ext'und nicht--include '.ext'
gbyte
13

Hier ist der wichtige Teil der Manpage:

Während die Liste der zu übertragenden Dateien / Verzeichnisse erstellt wird, prüft rsync nacheinander jeden zu übertragenden Namen anhand der Liste der Einschluss- / Ausschlussmuster, und es wird auf das erste übereinstimmende Muster reagiert: Wenn es sich um ein Ausschlussmuster handelt, handelt es sich um diese Datei übersprungen; Wenn es sich um ein Include-Muster handelt, wird dieser Dateiname nicht übersprungen. Wird kein passendes Muster gefunden, wird der Dateiname nicht übersprungen.

Zusammenfassen:

  • Wenn kein Muster übereinstimmt, wird eine Datei kopiert!
  • Der Algorithmus wird beendet, sobald ein Muster übereinstimmt

Etwas, das mit einem Schrägstrich endet, stimmt auch mit Verzeichnissen überein (wie z find -type d wäre).

Lassen Sie uns diese Antwort von oben auseinander ziehen.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Überspringen Sie keine Verzeichnisse
  2. Überspringen Sie keine .sh Dateien
  3. Überspringe alles
  4. (Überspringen Sie implizit nichts, aber die obige Regel verhindert, dass die Standardregel jemals auftritt.)

Schließlich verhindert --prune-empty-directoriesdie erste Regel, dass überall leere Verzeichnisse erstellt werden.

Jim Hunziker
quelle
Vielen Dank für die Erklärung, was los ist. Jetzt besteht eine viel bessere Chance, dass ich den Befehl nicht vergesse.
MohamedEzz
3
‚‘ Der Algorithmus quitt einmal irgendwelche Muster entsprechen“ - dies ist der Schlüssel, und keiner der höher bewerteten Antworten erklärt es so klar und up-front , wie Sie hier taten Natürlich ist das. Ist in der Manpage somehwere, und wenn ich Ich hätte das Ganze sorgfältig gelesen, das hätte ich gesehen. Trotzdem danke.
TheDudeAbides
0

Wenn jemand danach sucht ... Ich wollte nur bestimmte Dateien und Ordner rsyncieren und habe es mit diesem Befehl geschafft: rsync --include-from=rsync-files

Mit rsync-Dateien:

my-dir/
my-file.txt

- /*
Pascal Polleunus
quelle
0

Schrieb diese praktische Funktion und fügte meine Bash-Skripte oder ein ~/.bash_aliases. Lokale Synchronisierung unter Linux mit Bash getestet und awkinstalliert. Es klappt

selrsync(){
# selective rsync to sync only certain filetypes;
# based on: https://stackoverflow.com/a/11111793/588867
# Example: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift; #accepts comma separated list of types. Must be the first argument.
includes=$(echo $types| awk  -F',' \
    'BEGIN{OFS=" ";}
    {
    for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
    }')
restargs="$@"

echo Command: rsync -avz --prune-empty-dirs --include="*/" $includes --exclude="*" "$restargs"
eval rsync -avz --prune-empty-dirs --include="*/" "$includes" --exclude="*" $restargs
}

Vorteile:

kurz handlich und erweiterbar, wenn man mehr Argumente hinzufügen möchte (dh --dry-run ).

Beispiel:

selrsync 'tsv,csv' ./source ./target --dry-run
Biocyberman
quelle