web-dev-qa-db-ja.com

Rsyncフィルター:1つのパターンのみをコピーする

LaTeXからコンパイルしたすべてのPDFのみを格納するディレクトリを作成しようとしています。各プロジェクトを別々のフォルダーに保存し、すべてをLaTeXという大きなフォルダーに格納するのが好きです。だから私は走ってみました:

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

これにより、~/LaTeX/内のすべてのPDFが検出され、出力フォルダーに転送されます。これは機能しません。 「*.pdf」に一致するものが見つからないことがわかります。このフィルターを省略した場合、コマンドはLaTeXの下のすべてのプロジェクトフォルダー内のすべてのファイルを一覧表示します。したがって、*。pdfフィルターの問題です。 ~/をホームディレクトリへの完全なパスに置き換えてみましたが、効果がありませんでした。

私は、zshを使用しています。私はbashで同じことを試してみましたwithすべてのサブディレクトリのすべてのファイルをリストするフィルター...ここで何が起こっているのですか?

Rsyncが私のPDFのみのフィルターを理解しないのはなぜですか?


OK。だから更新:いいえ私はやっています

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

そして、これは私にファイルリスト全体を与えます。すべてが最初のパターンに一致するので...

142
Seamus

TL、DR:

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

Rsyncはソースを宛先にコピーします。ソースとして*.pdfを渡すと、シェルはこれを現在のディレクトリの.pdf拡張子を持つファイルのリストに展開します。ソースとしてディレクトリを渡さなかったため、再帰的なトラバーサルは発生しません。

したがって、rsync -a ~/LaTeX/ ~/Output/を実行する必要がありますが、.pdfファイルのみをコピーするようにrsyncに指示するフィルターが必要です。マニュアルを読むと、Rsyncのフィルター規則は気が遠くなるように見えるかもしれませんが、いくつかの単純な規則だけで多くの例を構築できます。

  • 包含と除外:

    • 名前または場所でファイルを除外するのは簡単です:--exclude=*~--exclude=/some/relative/location(ソース引数を基準にして、たとえば~/LaTeX/some/relative/locationを除外します)。
    • いくつかのファイルまたは場所のみを照合する場合は、それらを含めますそれらにつながるすべてのディレクトリを含める(たとえば、--include=*/を使用)。次に、残りを--exclude='*'で除外します。それの訳は:
    • ディレクトリを除外すると、その下のすべてが除外されます。除外されたファイルはまったく考慮されません。
    • ディレクトリを含めても、その内容は自動的には含まれません。最近のバージョンでは、--include='directory/***'がそれを行います。
    • ファイルごとに、最初に一致したルールが適用されます(一致しないものはすべて含まれます)。
  • パターン:

    • パターンに/が含まれていない場合は、ファイル名sansディレクトリーに適用されます。
    • パターンが/で終わる場合、それはディレクトリにのみ適用されます。
    • パターンが/で始まる場合、rsyncに引数として渡されたディレクトリからのパス全体に適用されます。
    • *単一のディレクトリコンポーネントの任意の部分文字列(つまり、/と一致することはありません)。 **は、パスの部分文字列に一致します。
  • ソース引数が/で終わる場合、その内容がコピーされます(rsync -r a/ bは、b/fooごとにa/fooを作成します)。それ以外の場合は、ディレクトリ自体がコピーされます(rsync -r a bb/aを作成します)。


したがって、ここでは*.pdfを含め、それらを含むディレクトリを含め、その他すべてを除外する必要があります。

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

これにより、一致するファイルまたはサブディレクトリが含まれていないディレクトリも含めて、すべてのディレクトリがコピーされることに注意してください。これは--Prune-empty-dirsオプションで回避できます(明示的に照合してもディレクトリをコピーできないため、これは汎用的なソリューションではありませんが、これはまれな要件です)。

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

デフォルトではすべてを含めるため、転送するファイルを含め、すべて明示的に除外する必要がありますafter。 --dry-runを削除して、実際にファイルを転送します。

あなたが始める場合:

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

次に、貪欲なマッチングにより、すべてがすぐに除外されます。

あなたがしようとすると:

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

次に、最上位フォルダのPDFファイルのみが転送されます。ディレクトリは「*」で除外されているため、どのディレクトリにも従いません。

30
jmanning2k

*.pdfのようなパターンを使用する場合、シェルはそのパターンを「展開」します。つまり、パターンを現在のディレクトリ内のすべての一致で置き換えます。実行中のコマンド(この場合はrsync)は、パターンを使用しようとしたことを認識していません。

zshを使用している場合は、簡単な解決策があります。ただし、**パターンを使用して、フォルダーを再帰的に照合できます。これを試して:

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

findとファイルの中間リスト(files_to_copy)問題を解決します。あなたがあなたのホームディレクトリにいることを確認してください:

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

Bashでテスト済み。

13
Derek Frye

manpage の「INCLUDE/EXCLUDE PATTERN RULES」セクションで判断すると、これを行う方法は次のとおりです。

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

これとkbrdの答えの重要な違いは、--include="*/"フラグです。これは、rsyncに、名前が何であれ、検出したディレクトリをコピーするよう指示します。これは、サブディレクトリをコピーするように指示されていない限り、rsyncがサブディレクトリに再帰しないために必要です。

また、引用符により、シェルが現在のディレクトリを基準にしてファイル名にパターンを展開することを防ぎ、次のいずれかを実行することに注意してください。

  1. フィルターを成功させ、混乱させる(そのようなフラグの真ん中にある可能性は低いですが、誰かが--include=foo.pdfという名前のファイルをいつ作成するかは本当にわかりません)

  2. 失敗し、コマンドを実行する代わりにエラーが発生する可能性があります(デフォルトでzshが実行することを発見しました)。

9
SamB

これは私の好ましい解決策です:

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

findコマンドは、rsyncの包含/除外ルールよりも理解しやすいです:-)

PDFファイルのみをコピーする場合は、.jpg.pdf

3
guettli

これはどう:

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

以下は、findを使用せずに機能するものです。すでに投稿されている回答との違いは、フィルタールールの順序です。 rsyncコマンドのフィルター規則はiptable規則とよく似ており、ファイルが最初に一致する規則が使用されます。 manual page から:

転送するファイル/ディレクトリのリストが作成されると、rsyncは転送する各名前をインクルード/除外パターンのリストに対して順番にチェックし、最初に一致したパターンが実行されます。除外パターンの場合、そのファイルはスキップされました。インクルードパターンの場合、そのファイル名はスキップされません。一致するパターンが見つからない場合、ファイル名はスキップされません。

したがって、次のようなコマンドが必要です。

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

「**。pdf」パターンに注意してください。 manページ によると:

パターンに/(末尾の/を数えない)または "**"が含まれている場合、先頭のディレクトリを含む完全なパス名と照合されます。パターンに/または "**"が含まれていない場合は、ファイル名の最後の構成要素に対してのみ照合されます。 (アルゴリズムは再帰的に適用されるので、「完全なファイル名」は実際には開始ディレクトリから下のパスの任意の部分にすることができます

私の小さなテストでは、これはディレクトリツリーの下で再帰的に機能し、PDFのみを選択します。

2
Steven D

ソースディレクトリ内からヘッダーのみを含むディレクトリ(../include)を生成するには:

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

これは、すべての空のディレクトリとディレクトリbuildを除外します

0
SCG82