「ファイル名を持つファイルB」から「ファイル名を持つファイルA」、つまり「Aから削除された項目」を減算または減算しませんでしたか?

「ファイル名を持つファイルB」から「ファイル名を持つファイルA」、つまり「Aから削除された項目」を減算または減算しませんでしたか?

rsync(できるので)大きなフォルダAをBにコピーしたりバックアップしたいです。https://stackoverflow.com/a/65485164/1707015

うまくいきますが、時にはBをクリーンアップしてBから古いファイルを削除したいです(Aから削除された場合)。

Aから削除されたファイルをインポートする必要があります(Bでも削除できるように)。

$ cat A_files.txt  # for example: think the small letters as paths like ./some/path/file.yaml
a
c
d
e
f

$ cat B_files.txt
a
b
c
d

$ \grep -f A_files.txt -F -v B_files.txt
b

(バックスラッシュは\色などのgrepエイリアスを使用しないためです。)

これはうまくいきますが、小さなファイルにのみ当てはまります。ファイル名あたり100MBを超えるファイルの場合は、100GB以上のRAMが必要です。

誰かがよりリソース効率の良いバリエーションを提供できますか?もちろん可能ですrsync。しかし、楽しさや練習目的で使用するためのものではありません。

ベストアンサー1

リストの結合/減算の場合、標準コマンドはですcomm。ソートされたファイル行で動作します。

B_files.txtしたがって、行が含まれていない場合A_files.txt

export LC_ALL=C # for a simple and deterministic order and allow any byte
                # in file names.
comm -23 <(sort A_files.txt) <(sort B_files.txt)

ファイルがすでにソートされている場合:

comm -23 A_files.txt B_files.txt

このアプローチ(またはあなたのアプローチ)は、ファイル名に改行文字を含めることができるため、任意のファイル名には機能しません。ワイヤー

GNUシステムを使用している場合は、NULを使用して行の代わりにレコードを区切り、オプションを使用できます-zsortcomm

別の方法は、zshの配列の組み合わせ/減算演算子を使用することです。

cd /path/to/A || exit
A_regular_files=(**/*(ND.))
cd /path/to/B || exit
B_regular_files=(**/*(ND.))

files_in_B_but_not_in_A=(${B_regular_files:|A_regular_files})

また、この-xオプションを渡さないと、部分grep文字列は一致します。たとえば、grep -F foo/bar一致します。blah/foo/barrage

おすすめ記事