it-swarm.com.de

Rsync-Filter: Nur ein Muster kopieren

Ich versuche, ein Verzeichnis zu erstellen, in dem alle und nur meine aus LaTeX kompilierten PDF-Dateien gespeichert sind. Ich mag es, jedes Projekt in einem separaten Ordner zu speichern, der sich alle in einem großen Ordner namens LaTeX befindet. Also habe ich versucht zu laufen:

rsync -avn *.pdf ~/LaTeX/ ~/Output/

das sollte alle PDFs in ~/LaTeX/ finden und in den Ausgabeordner übertragen. Das funktioniert nicht. Es sagt mir, dass keine Übereinstimmungen für "*.pdf" Gefunden wurden. Wenn ich diesen Filter weglasse, listet der Befehl alle Dateien in allen Projektordnern unter LaTeX auf. Es ist also ein Problem mit dem * .pdf-Filter. Ich habe versucht, ~/ Durch den vollständigen Pfad zu meinem Home-Verzeichnis zu ersetzen, aber das hatte keine Auswirkungen.

Ich benutze zsh. Ich habe versucht, dasselbe in bash und sogar mit dem Filter zu tun, der jede einzelne Datei in jedem Unterverzeichnis auflistet ... Was ist hier los?

Warum versteht rsync meinen PDF-Filter nicht?


OK. Also Update: Nein, ich versuche es

rsync -avn --include="*/" --include="*.pdf" LaTeX/ Output/

Und das gibt mir die ganze Dateiliste. Ich denke, weil alles zum ersten Muster passt ...

142
Seamus

TL, DR:

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Rsync kopiert die Quelle (n) zum Ziel. Wenn Sie *.pdf Als Quellen übergeben, erweitert die Shell dies auf die Liste der Dateien mit der Erweiterung .pdf Im aktuellen Verzeichnis. Es findet keine rekursive Durchquerung statt, da Sie kein Verzeichnis als Quelle übergeben haben.

Sie müssen also rsync -a ~/LaTeX/ ~/Output/ Ausführen, aber mit einem Filter, der rsync anweist, nur .pdf - Dateien zu kopieren. Die Filterregeln von Rsync können beim Lesen des Handbuchs entmutigend wirken, aber Sie können viele Beispiele mit nur wenigen einfachen Regeln erstellen.

  • Ein- und Ausschlüsse:

    • Das Ausschließen von Dateien nach Name oder Speicherort ist einfach: --exclude=*~, --exclude=/some/relative/location (Relativ zum Quellargument, z. B. schließt dies ~/LaTeX/some/relative/location Aus).
    • Wenn Sie nur einige Dateien oder Speicherorte abgleichen möchten, fügen Sie sie ein, schließen Sie jedes Verzeichnis ein, das zu ihnen führt (zum Beispiel mit --include=*/), Und schließen Sie den Rest mit --exclude='*'. Das ist weil:
    • Wenn Sie ein Verzeichnis ausschließen, schließt dies alles darunter aus. Die ausgeschlossenen Dateien werden überhaupt nicht berücksichtigt.
    • Wenn Sie ein Verzeichnis einschließen, enthält dies nicht automatisch dessen Inhalt. In neueren Versionen wird --include='directory/***' Dies tun.
    • Für jede Datei gilt die erste Übereinstimmungsregel (und alles, was nie übereinstimmt, ist enthalten).
  • Muster:

    • Wenn ein Muster kein / Enthält, gilt es für den Dateinamen ohne Verzeichnis.
    • Wenn ein Muster mit / Endet, gilt es nur für Verzeichnisse.
    • Wenn ein Muster mit / Beginnt, gilt es für den gesamten Pfad aus dem Verzeichnis, das als Argument an rsync übergeben wurde.
    • * Eine beliebige Teilzeichenfolge einer einzelnen Verzeichniskomponente (d. H. Entspricht niemals /); ** Entspricht einer beliebigen Pfadzeichenfolge.
  • Wenn ein Quellargument mit einem / Endet, wird sein Inhalt kopiert (rsync -r a/ b Erstellt b/foo Für jeden a/foo). Andernfalls wird das Verzeichnis selbst kopiert (rsync -r a b Erstellt b/a).


Daher müssen wir hier *.pdf Einschließen, Verzeichnisse einschließen, die sie enthalten, und alles andere ausschließen.

rsync -a --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/

Beachten Sie, dass dadurch alle Verzeichnisse kopiert werden, auch diejenigen, die keine übereinstimmende Datei oder Unterverzeichnis enthalten. Dies kann mit der Option --Prune-empty-dirs Vermeidet werden (dies ist keine universelle Lösung, da Sie ein Verzeichnis dann nicht kopieren können, selbst wenn Sie es explizit abgleichen, aber das ist eine seltene Anforderung).

rsync -am --include='*.pdf' --include='*/' --exclude='*' ~/LaTeX/ ~/Output/
rsync -av --include="*/" --include="*.pdf" --exclude="*" ~/Latex/ ~/Output/ --dry-run

Standardmäßig wird alles eingeschlossen, daher müssen Sie explizit alles ausschließen nach einschließlich der Dateien, die Sie übertragen möchten. Entfernen Sie --dry-run, um die Dateien tatsächlich zu übertragen.

Wenn Sie beginnen mit:

--exclude '*' --include '*.pdf'

Dann schließt das gierige Matching alles sofort aus.

Wenn du es versuchst:

--include '*.pdf' --exclude '*' 

Dann werden nur PDF-Dateien im Ordner der obersten Ebene übertragen. Es folgen keine Verzeichnisse, da diese durch '*' ausgeschlossen sind.

30
jmanning2k

Wenn Sie ein Muster wie *.pdf Verwenden, "erweitert" die Shell dieses Muster, d. H. Sie ersetzt das Muster durch alle Übereinstimmungen im aktuellen Verzeichnis. Der Befehl, den Sie ausführen (in diesem Fall rsync), weiß nicht, dass Sie versucht haben, ein Muster zu verwenden.

Wenn Sie zsh verwenden, gibt es jedoch eine einfache Lösung: Das Muster ** Kann verwendet werden, um Ordner rekursiv abzugleichen. Versuche dies:

rsync -avn ~/LaTeX/**/*.pdf ~/Output/
15
Marcel Stimberg

Sie können find und eine Zwischenliste von Dateien (files_to_copy) um Ihr Problem zu lösen. Stellen Sie sicher, dass Sie sich in Ihrem Home-Verzeichnis befinden, und dann:

find LaTeX/ -type f -a -iname "*.pdf" > files_to_copy && rsync -avn --files-from=files_to_copy ~/ ~/Output/ && rm files_to_copy

Getestet mit Bash.

13
Derek Frye

Gemessen am Abschnitt "INCLUDE/EXCLUDE PATTERN RULES" der manpage ist der Weg, dies zu tun

rsync -avn --include="*/" --include="*.pdf" ~/Latex/ ~/Output/

Der entscheidende Unterschied zwischen dieser und der Antwort von kbrd ist das Flag --include="*/", Das rsync anweist, alle gefundenen Verzeichnisse zu kopieren, unabhängig davon, wie sie benannt sind. Dies ist erforderlich, da rsync nur dann in ein Unterverzeichnis zurückkehrt, wenn es angewiesen wurde, dieses Unterverzeichnis zu kopieren.

Beachten Sie außerdem, dass die Anführungszeichen die Shell daran hindern, die Muster auf Dateinamen relativ zum aktuellen Verzeichnis zu erweitern, und einen der folgenden Schritte ausführen:

  1. Erfolgreich sein und Ihren Filter durcheinander bringen (nicht allzu wahrscheinlich mitten in einer solchen Flagge, obwohl Sie wirklich nie wissen, wann jemand eine Datei mit dem Namen --include=foo.pdf Erstellen wird ...)

  2. Dies schlägt fehl und führt möglicherweise zu einem Fehler, anstatt den Befehl auszuführen (wie Sie festgestellt haben, dass zsh dies standardmäßig tut).

9
SamB

Dies ist meine bevorzugte Lösung:

find source_dir -iname '*.jpg' -print0 |  rsync -0 -v --files-from=- . destination_dir/

Der Befehl find ist leichter zu verstehen als die Einschluss-/Ausschlussregeln von rsync :-)

Wenn Sie nur PDF-Dateien kopieren möchten, ändern Sie einfach .jpg bis .pdf

3
guettli

Wie wäre es damit:

rsync -avn --include="*.pdf" ~/Latex/ ~/Output/
3
kbyrd

Hier ist etwas, das funktionieren sollte, ohne find zu verwenden. Der Unterschied zu bereits veröffentlichten Antworten besteht in der Reihenfolge der Filterregeln. Filterregeln in einem rsync-Befehl funktionieren ähnlich wie iptable-Regeln. Die erste Regel, mit der eine Datei übereinstimmt, wird verwendet. Aus der Handbuchseite :

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.

Daher benötigen Sie einen Befehl wie folgt:

rsync -avn --include="**.pdf" --exclude="*" ~/LaTeX/ ~/Output/

Beachten Sie das Muster "**. Pdf". Laut die Manpage :

wenn das Muster ein/(ohne ein nachfolgendes /) oder ein "**" enthält, wird es mit dem vollständigen Pfadnamen einschließlich aller führenden Verzeichnisse abgeglichen. Wenn das Muster kein/oder "**" enthält, wird es nur mit der endgültigen Komponente des Dateinamens abgeglichen. (Denken Sie daran, dass der Algorithmus rekursiv angewendet wird, sodass "vollständiger Dateiname" tatsächlich ein beliebiger Teil eines Pfads ab dem Startverzeichnis sein kann

In meinem kleinen Test funktioniert dies rekursiv im Verzeichnisbaum und wählt nur die PDFs aus.

2
Steven D

So generieren Sie ein Verzeichnis, das nur Header (../include) enthält, aus dem Quellverzeichnis:

rsync -avh --Prune-empty-dirs --exclude="build" --include="*/" --include="*.h" --exclude="*" ./* ../include/

Dies schließt alle leeren Verzeichnisse und das Verzeichnis build aus

0
SCG82