
最近我需要刪除很多重複。我正在合併三到四個檔案系統,並且希望經濟地使用空間。起初,fdupes
它似乎是完成這項工作的最佳工具,但我越來越遇到限制。
考慮命令fdupes -rdN somedirectory/
。這會產生某個目錄的子目錄中所有檔案的雜湊值。
當它遇到重複項時,它會刪除它們,以便所有內容都只有一份副本。
但是,如果我想保留somedirectory/subdirectory1/somefile
並且實際上有四個重複項,並且程式首先遇到其中一個重複項,該怎麼辦?然後它刪除了somedirectory/subdirectory1/somefile
我不想要的。
我希望能夠以某種方式指定要保留哪些重複項。到目前為止,處理重複項的標準程序(duff、FSLint)似乎都不允許這種行為的自動化。我不想自己動手,所以這就是我問這個問題的原因。
我希望能夠寫出類似的東西
killdupes -rdN --keep=filesin,somedirectories,separated,by,commas somedirectory/
答案1
雖然您尋求的功能沒有現貨fdupes
,但我分叉了fdupes
(我的叉子叫jdupes
)並且添加了一些功能,可以在某些情況下解決這個問題。例如,在上述情況下,您希望somedirectory/subdirectory1/somefile
在自動刪除重複項時保留(d
和N
一起切換)並且緊接其下沒有單獨的文件somedirectory
,可以將第一個和開關jdupes
輸入每個直接子目錄路徑(透過命令對文件進行排序) -行參數順序優先):subdirectory1
-O
jdupes -rdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3
這將自動刪除重複集中除一個文件之外的所有文件,並保證如果該集中包含一個文件,則該文件somedirectory/subdirectory1
將是第一個文件,從而自動成為該集中保留的文件。這種方法仍然存在明顯的限制,例如可能somedirectory/subdirectory1
會保留另一個重複項,而不是您想要保留的重複項,但在許多像您這樣的情況下,jdupes
參數順序選項作為解決方法就足夠了。
在不久的將來,我計劃添加一個過濾系統,該系統將能夠對文件的包含/排除、操作的保存以及在全局或每個參數的基礎上應用此類「過濾器堆疊」進行jdupes
大量控制。-N
這個功能是非常需要的;我設想這樣的「自動遞歸刪除非零重複項但始終保持somedirectory/subdirectory1/somefile
原樣」:
jdupes -rdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/
更新(2022-03-01):看一下2020 年新增-X
的擴充過濾器選項。nostr
onlystr
答案2
我在其他地方沒有看到這個:說你想要的是這個。您有 /mnt/folder-tree-1 /mnt/folder-tree-2。您不想刪除每個重複的文件,但如果樹 2 中存在一個文件,並且在樹 1 中存在具有完全相同的路徑和名稱的相同文件,請將其從樹 2 中刪除。
警告:這非常簡潔,如果您嘗試使用有限的 shell 技能複製貼上此內容,請小心。
fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt
fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line
do
if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt
then
echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2//|')\"
fi
done > rm-v2-dupes.sh
或全部寫在一行上:
fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt; fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line; do if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt; then echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|')\"; fi; done > rm-v2-dupes.sh
然後,檢查並執行 rm-v2-dupes.sh
答案3
將重複文件硬連結在一起怎麼樣?這樣,該空間僅使用一次,但它們仍然存在於所有路徑中。這樣做的問題是硬連結檔案應該就地修改(它們只能修改刪除檔案並使用新內容重新建立它)。另一種方法是將檔案符號連結在一起,儘管您在決定哪個「主」檔案是相同的問題。這可以透過以下腳本來完成(儘管請注意,這不會處理包含空格的檔案名稱)。
fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do
for DEST in $DESTS; do
ln -f $SOURCE $DEST
done
done
答案4
只是為了給之前的答案添加一個轉折。我多次使用了以下程式碼,稍微修改了先前的答案,簡單地| grep
隔離了我要從中刪除的資料夾。
`fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`
同樣,這將創建一個 sh 文件來刪除列出的所有文件,沒有註解行。當然,您仍然可以編輯該文件以註解掉要保留的特定行/文件。
對於大型目錄的另一個提示是對 txt 檔案執行 fdupes,然後嘗試| grep
並| sed
直到得到我想要的結果。
`fdupes -r -n -S /directory > duplicate-files.txt`
`cat duplicate-files.txt | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh`