有沒有比 fdupes -rdN 更精細的刪除重複項的方法?

有沒有比 fdupes -rdN 更精細的刪除重複項的方法?

最近我需要刪除很多重複。我正在合併三到四個檔案系統,並且希望經濟地使用空間。起初,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在自動刪除重複項時保留(dN一起切換)並且緊接其下沒有單獨的文件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的擴充過濾器選項。nostronlystr

答案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`

相關內容