web-dev-qa-db-ja.com

rsync:ディレクトリ構造を無視してすべてのファイルを再帰的に同期します

デスクトップからモバイルデバイスに音楽を同期するためのbashスクリプトを作成しようとしています。デスクトップがソースです。

Rsyncにファイルを再帰的に同期させ、ディレクトリ構造を無視する方法はありますか?デスクトップからファイルが削除された場合は、デバイスでも削除してほしい。

デスクトップのディレクトリ構造はこんな感じです。

    Artist1/
        Artist1/art1_track1.mp3
        Artist1/art1_track2.mp3
        Artist1/art1_track3.mp3
    Artist2/
        Artist2/art2_track1.mp3
        Artist2/art2_track2.mp3
        Artist2/art2_track3.mp3
    ...

デバイスに必要なディレクトリ構造は次のとおりです。

    Music/
        art1_track1.mp3
        art1_track2.mp3
        art1_track3.mp3
        art2_track1.mp3
        art2_track2.mp3
        art2_track3.mp3
    ...
14
Srinath Sridhar

単に:

rsync -a --delete --include=*.mp3 --exclude=* \
    pathToSongs/Theme*/Artist*/. destuser@desthost:Music/.

パス階層のレベル数が固定されている場合は、この作業を実行します。

警告:2つの曲ファイルの名前がまったく同じで、同じ宛先ディレクトリにある場合、バックアップではそのうちの1つが失われます。

そうでなければ、そしてあなたの質問に厳密に答えるためにディレクトリ構造を無視してあなたは bashshopt -s globstar機能を使うことができます:

shopt -s globstar
rsync -a --delete --include=*.mp3 --exclude=* \
    pathToSongsRoot/**/. destuser@desthost:Music/.

findコマンドにフォークする必要はまったくありません。

ディレクトリ構造を無視して、すべてのファイルを再帰的に同期します

質問に厳密に答えるために、拡張機能に限定されてはなりません。

shopt -s globstar
rsync -d --delete sourceRoot/**/. destuser@desthost:destRoot/.

これにより、ディレクトリもコピーされますが、コンテンツは含まれません。すべてのファイルおよびディレクトリは、destRoot/の同じレベルに保存されます。

警告:同じ名前のいくつかの異なるファイルがdefferentsディレクトリに存在する場合、それらは宛先で単に上書きされ、rsync中に、最終的に1つだけをランダムに保存します。

15
F. Hauri

これは最近のオプションかもしれませんが、--no-relativeのドキュメントに記載されているオプション--files-fromが表示され、うまく機能しました。

find SourceDir -name \*.mp3 | rsync -av --files-from - --no-relative . DestinationDir/
8
haridsv

あなたの質問への答え:いいえ、rsyncはこれを単独で行うことはできません。しかし、他のツールの助けを借りて、そこにたどり着くことができます...数回の試行の後、私はこれを思いつきました:

rsync -d --delete $(find . -type d|while read d ; do echo $d/ ; done) /targetDirectory && rmdir /targetDirectory/* 2>&-

難しさはこれです:ターゲット位置でファイルの削除を有効にするには、次のことを行う必要があります。

  1. rsyncのソースとしてディレクトリを指定します(ソースがファイルのリストである場合は削除されません)。
  2. ソースの完全なリストを一度に提供します(ループ内のrsyncは、ターゲットでのみ最後のディレクトリの内容を提供します)。
  3. ディレクトリ名をスラッシュで終了します(それ以外の場合は、ターゲットディレクトリにディレクトリを作成します)

したがって、コマンド置換($()で囲まれたもの)はこれを行います。すべてのディレクトリを検索し、ディレクトリ名の最後にスラッシュ(/)を追加します。これで、rsyncはソースディレクトリのリストを確認します。これらはすべてスラッシュで終了しているため、その内容をターゲットディレクトリにコピーします。オプション-dは、再帰的にコピーしないように指示します。

2番目のトリックはrmdir /targetDirectory/*で、rsyncが作成した空のディレクトリを削除します(ただし、そうするように依頼していません)。

ここでテストしたところ、ソースツリーで削除されたファイルの削除は問題なく機能しました。

1
holgero

ファイルのリストを作成できれば、すでに問題は解決しています。試してみてください:

find /path/to/src/ -name \*.mp3 > list.txt
rsync -avi --no-relative --progress --files-from=list.txt / user@server:/path/to/dest

新しいファイルに対してスクリプトを再度実行すると、不足しているファイルのみがコピーされます。

リストが気に入らない場合は、1つの文を試してください(ただし、これは別のロジックです)

find /path/to/src/ -name \*.mp3 -type f \
  -exec rsync -avi --progress {} user@server:/path/to/dest/  \;

この場合、文の種類によっては以前にファイルリストを作成できないため、毎回各ファイルを要求します。

0
mariovials