29

タイトルからわかるように、フォルダをファイルのリストと同期しようとしています。このコマンドで、リストにないdest /内のすべてのファイルが削除されることを期待していましたが、削除されませんでした。

だから私は少し検索して、rsyncがこれを行うことができないことを今知っています。

しかし、私はそれが必要です、それであなたはそれをする方法を知っていますか?

PS:リストはPythonスクリプトによって作成されるため、ソリューションでPythonコードを使用することは想像に難くありません。

編集、具体的にしましょう:

リストは次のようになります。

/home/max/Musik/Coldplay/Parachutes/Trouble.mp3
/home/max/Musik/Coldplay/Parachutes/Yellow.mp3
/home/max/Musik/Coldplay/A Rush of Blood to the Head/Warning Sign.mp3
/home/max/Musik/Coldplay/A Rush of B-Sides to Your Head/Help Is Around the Corner.mp3
/home/max/Musik/Coldplay/B-Sides (disc 3)/Bigger Stronger.mp3

そしてこのようなコマンド:

rsync --delete --files-from=/tmp/list / /home/max/Desktop/foobar/

これは機能しますが、行を削除してもfoobar/では削除されません。

編集2:

rsync -r --include-from=/tmp/list --exclude=* --delete-excluded / /home/max/Desktop/foobar/

それはどちらも機能しません...

4

7 に答える 7

22

おそらく、代わりにインクルードパターンのリストを使用してこれを行い、--delete-excluded(名前が示すように)使用できますか?何かのようなもの:

rsync -r --include-from=<patternlistfile> --exclude=* --delete-excluded / dest/

ファイル名にワイルドカード文字(、、および)が含まれている可能性がある場合*?[Pythonを変更してそれらをエスケープする必要があります。

re.sub("([[*?])", r"\\\1", "abc[def*ghi?klm")

編集:パターンベースのマッチングは、効率上の理由から、除外パターンに一致するディレクトリに再帰しない--files-fromという点とは少し異なります。rsyncしたがって、ファイルが入っていて/some/dir/some/other/dirパターンファイルは次のようになっている必要があります。

/some/
/some/dir/
/some/dir/file1
/some/dir/file2
/some/other/
/some/other/dir/
/some/other/dir/file3
...

または、すべてのファイルが同じディレクトリにある場合は、コマンドを少し書き直すことができます。

rsync -r --include-from=<patternlistfile> --exclude=* --delete-excluded /some/dir/ dest/

そして、あなたのパターンは次のようになります。

/file1
/file2

編集:それについて考えると、1つのパターンですべてのディレクトリを含めることができます:

/**/

しかし、そうすると、ディレクトリツリー全体になってしまい、dest/おそらくあなたが望むものではないでしょう。しかし、それを(空のディレクトリを削除する)と組み合わせると、それを-m解決するはずです-したがって、コマンドは次のようになります:

rsync -m -r --delete-excluded --include-from=<patternfile> --exclude=* / dest/

およびパターンファイル:

/**/
/some/dir/file1
/some/other/dir/file3
于 2009-11-28T22:29:29.383 に答える
12

これは正確には解決策ではありませんが、ここに来る人はこれが便利だと思うかもしれません。rsync 3.1.0以降、--delete-missing-argsを使用して2つのディレクトリを同期すると、宛先ディレクトリのファイルを削除するパラメータがあります--files-from/tmp/listコピーしたいファイルと一緒に削除されたファイルを指定する必要があります:

rsync --delete-missing-args --files-from=/tmp/list /source/dir /destination/dir

詳細については、manページを参照してください。

于 2015-06-12T15:17:57.877 に答える
10

あなたが説明したように、コマンド

rsync -r --delete --files-from=$FILELIST user@server:/ $DEST/

$ FILELISTからのエントリが削除されたときに、宛先のコンテンツを削除しません。簡単な解決策は、代わりに次を使用することです。

mkdir -p $DEST
rm -rf $TEMP
rsync -r --link-dest=$DEST --files-from=$FILELIST user@server:/ $TEMP/
rm -r $DEST
mv $TEMP $DEST

これは、空の宛先を使用するようにrsyncに指示します。link-dest-directoryにすでに存在するファイルは、ローカルでハードリンクされており、コピーされません。最後に、古い宛先が新しい宛先に置き換えられます。$ DESTが存在しない場合、最初のmkdirは空の$ DESTを作成して、rsyncエラーを防ぎます。($変数は、それぞれのファイルまたはディレクトリへのフルパスを運ぶと想定されています。)

ハードリンクには若干のオーバーヘッドがありますが、複雑なinclude/exclude-strategiesをいじる必要はありません。

于 2013-03-03T23:20:51.363 に答える
4

m4tからインスピレーションを得ていますが、クリーンアップに...rsyncを使用しています

rsync -r --link-dest=$dst --files-from=filelist.txt user@server:$source/ $temp
rsync -ra --delete --link-dest=$temp $temp/ $dest
于 2013-03-13T11:23:38.433 に答える
1

明示的なビルド--exclude-from=...は、ファイルのリストを同期する唯一の方法のようです。

stdin = subprocess.PIPE
other_params.append("--exclude-from=-") #from stdin 

p = subprocess.Popen( 'rsync -e ssh -zthvcr --compress-level=9 --delete'.split() + other_params + [src, dst], stdin =  PIPE)

if relative_files_list != None:
    #hack: listing of excluded files seems the only way to delete unwanted files at destination
    files = set(map(norm_fn, relative_files_list)) #make hash table, for huge lists
    for path, ds, fs in os.walk(src):
        for f in fs:
            rel_path_f = norm_fn(os.path.relpath(os.path.join(path, f), src))
            if rel_path_f not in files:
                #print 'excluding', rel_path_f.replace('\\', '/')
                p.stdin.write(rel_path_f + '\n')
    p.stdin.close()
assert 0 == p.wait()
于 2010-11-03T13:45:16.693 に答える
0

この質問はずっと前に行われたことを私は知っていますが、私は答えに満足していませんでした。

によって作成されたプレイリストを想定して、問題を解決した方法は次のmpdとおりです。

#!/bin/bash                                                                 

playlist_path="/home/cpbills/.config/mpd/playlists"
playlist="${playlist_path}/${1}.m3u"
music_src="/home/cpbills/files/music"
music_dst="/mnt/sdcard/music/"

if [[ -e "$playlist" ]]; then
  # Remove old files
  find "$music_dst" -type f | while read file; do
    name="$(echo "$file" | sed -e "s!^$music_dst!!")"
    if ! grep -qF "$name" "$playlist"; then
      rm "$file"
    fi
  done

  # Remove empty directories
  find "$music_dst" -type d -exec rmdir {} \; 2>/dev/null

  rsync -vu \
      --inplace \
      --files-from="$playlist" \
      "$music_src" "$music_dst"
else
  printf "%s does not exist\n" "$playlist" 1>&2
  exit 1
fi
于 2015-02-01T01:37:05.657 に答える
-1

rsyncは、特に便利なことの中でも、ディレクトリの同期を維持するのに理想的です。SOURCEに正確なコピーがあり、DESTにあるファイルを削除したい場合は、それらをSOURCEから削除できrsync --deleteます。オプションにより、それらはDESTからも削除されます。

ただし、削除するファイルのリストが任意にある場合は、SSHを使用してそれを実行することをお勧めします。

ssh user@remote.host.com rm /path/to/file1 /path/to/file2

rmこれにより、リモートホストでコマンドが実行されます。

Pythonを使用すると、次のことができます。

import subprocess
FileList = ['/path/to/file1', '/path/to/file2']
subprocess.call(['ssh', 'dAnjou@my.server.com', 'rm'] + FileList)

〜お楽しみください

于 2009-11-28T22:23:23.950 に答える