
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を使用して行の代わりにレコードを区切り、オプションを使用できます-z
。sort
comm
別の方法は、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
答え2
私は次のことを思い出しました。
MY_SOURCE=A_files.txt
readarray -t MY_TARGET_ARRAY < B_files.txt
for LINE in "${MY_TARGET_ARRAY[@]}"; do
if ! grep -q "${LINE}" "${MY_SOURCE}"; then
echo "${LINE}";
fi;
done
まだテストされていません。不足している問題-x
および/または欠落している-F
問題がある可能性がありますgrep
。