
我正在尋找以下問題的Linux解決方案:
給定兩個包含大量文件的目錄。所有檔案名稱都是隨機的,並且兩個目錄中的檔案名稱都不同。但是,兩個目錄中的某些檔案的內容是相同的。
我想將兩個目錄中出現的所有檔案複製到第三個目錄。 (「同時出現」是指內容相同但名稱相同。)
答案1
假設您的檔案名稱沒有任何空格,且任一目錄中都沒有子目錄,則下列命令會列印具有符合 MD5 和的檔案名稱對:
join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort)
若要僅取得其中一個檔案名,請使用-o 1.2
或-o 2.2
。
如果檔案名稱(或路徑)可能包含空格,則您需要更加聰明。
如果目錄可能有多個名稱的相同文件,那麼您還需要更加聰明——並且需要準確地決定要做什麼。一種可能性是在進行連接之前過濾掉重複項:
join -o 1.2,2.2 <(md5sum $D1/* | sort | uniq -w16) \
<(md5sum $D2/* | sort | uniq -w16)
不使用sum
sum
輸出16位元校驗和;如果每個目錄中有數百個文件,則在比較 16 位元校驗和時很可能會得到誤報。md5sum
也不是絕對安全,但與 128 位元校驗和發生衝突的可能性很小。如有疑問,並且如果確實很重要,cmp
您也可以查看這些文件:
join -o 1.2,2.2 <(md5sum $D1/* | sort) <(md5sum $D2/* | sort) |
while read F1 F2; do
if cmp -s $F1 $F2; then
cp F1 $D3
fi
done
(同樣,如果檔案名稱中可能包含空格,則這將無法運作。)
答案2
使用您最喜歡的 shell 來編寫此偽代碼:
cd D1; sum * | while read l; do echo "D1 $l"; done >/tmp/foo
cd D2; sum * | while read l; do echo "D2 $1"; done >>/tmp/foo
sort -n /tmp/foo | awk '
$1 == prev_cs { echo "cp $3 dest"}
/prev_cs = $1/
' | shell
如果您願意,可以在發布副本之前保存 awk 輸出以供查看
答案3
這可能會完成這項工作,就像 mpez0 的 ans 複製重複項一樣。
find {tst1,tst2} -exec sum {} {} \; 2> /dev/null | sort | uniq