jdupes 找到重複檔案以後,可以用四種完全不同的方式處理它們:
-B --dedupe:讓重複檔案共享底層資料區塊;-l --link-soft:把重複副本替換為相對符號連結;-L --link-hard:把重複副本替換為硬連結;-d --delete:互動選擇要保留的檔案,並刪除其餘副本。
這四個選項都能減少重複資料,但不能簡單理解為四種寫法不同的“刪除重複檔案”。
它們改變的是不同層次的物件:資料區塊、inode、路徑引用或目錄項目。
選擇錯誤時,最麻煩的往往不是當場報錯,而是幾個月後某個程式修改、移動或刪除檔案,才發現其他路徑也受到了影響。
本文從檔案系統規格和行為出發,說明四種模式的真實區別、適用場景、限制條件和驗證方法。
特別提醒:
jdupes -d是會刪除檔案的操作。不要把同一個目錄重複寫入命令列,也不要在沒有充分理解符號連結走訪行為時把-d與-s或--symlinks一起使用。
先看結論:四種方式的核心區別
| 選項 | 處理結果 | 路徑是否保留 | inode 是否獨立 | 後續修改是否相互影響 | 主要限制 |
|---|---|---|---|---|---|
-B --dedupe |
共享相同物理資料區塊 | 全部保留 | 是 | 通常不影響,寫入時 CoW 分離 | 檔案系統必須支援去重或克隆介面 |
-l --link-soft |
副本變為相對符號連結 | 路徑名保留,但類型變為 symlink | symlink 自有 inode,內容來自目標 | 修改連結指向的內容會修改目標檔案 | 目標移動或刪除後可能成為斷鏈 |
-L --link-hard |
多個路徑指向同一 inode | 全部保留 | 否 | 會影響,因為本質是同一個檔案 | 不能跨檔案系統,應用語義可能變化 |
-d --delete |
刪除未被選擇保留的副本 | 只保留選中的路徑 | 不適用 | 不會聯動,但被刪路徑徹底消失 | 選擇錯誤會直接丟失路徑和中繼資料 |
如果只記住一句話,可以這樣判斷:
- 希望各個檔案仍然獨立,且檔案系統支援 CoW:優先考慮
-B; - 明確需要多個檔名共同代表同一個檔案:考慮
-L; - 明確希望某些路徑只是另一個檔案的引用:考慮
-l; - 確認多餘路徑沒有保留價值:才使用
-d。
jdupes 如何確認兩個檔案相同
處理方式雖然不同,但前面的重複檔案識別流程相同。
按照 jdupes 官方手冊,預設匹配過程依次包括:
- 比較檔案大小;
- 比較部分檔案雜湊;
- 比較完整檔案雜湊;
- 最後進行逐位元組比較。
只有透過這些階段的檔案,才會進入同一個重複檔案集合。
因此,預設模式並不是“檔名相同就算重複”,也不是“雜湊相同就立即執行操作”。
不帶任何動作選項時,jdupes 預設只列印重複檔案集合:
|
|
不同集合之間以空行分隔。
在真正使用 -B、-l、-L 或 -d 以前,應當先執行一次只讀掃描,確認路徑範圍和匹配結果符合預期。
不要為追求速度繞過最終驗證
-Q --quick 會跳過逐位元組確認,只依賴雜湊結果。
官方手冊明確把它標記為存在資料丟失風險。
-T --partial-only 的風險更高,因為它只依據檔案開頭的部分雜湊進行匹配。
在執行刪除、連結或 CoW 去重時,不應為了縮短掃描時間而隨意加入這兩個選項。
本文後續示例均使用預設的完整確認流程。
-B --dedupe:保留獨立檔案,共享資料區塊
基本命令如下:
|
|
-B 會請求檔案系統對重複檔案執行底層去重。
官方手冊把這一過程稱為 copy-on-write、CoW、cloning 或 reflink 去重。
從目錄層看,原來的檔名都還在。
從 inode 層看,它們仍然是彼此獨立的檔案。
從資料區塊層看,相同內容可以引用同一組物理塊,從而減少實際佔用空間。
CoW 去重後的結構
假設有兩個完全相同的檔案:
|
|
兩個路徑對應不同 inode,但相同區段共享底層資料區塊。
如果以後修改 b.iso 的一部分,支援 CoW 的檔案系統會為變化的區段分配新塊:
|
|
未修改的區段仍可共享,發生寫入的區段則分離。
這正是 -B 與硬連結最關鍵的區別。
為什麼它適合仍可能被修改的檔案
使用硬連結時,多個路徑實際上是同一個 inode。
程式透過任一路徑原地寫入內容,其他路徑看到的內容也會改變。
使用 CoW 去重時,檔案仍然獨立。
只要檔案系統正確實現 CoW,修改一個檔案不會把另一個檔案同步改掉。
因此,以下場景通常更適合 -B:
- 多份虛擬機器映象;
- 多個版本的備份目錄;
- 照片或影片素材副本;
- 軟體倉庫中的重複安裝包;
- 內容相同但生命週期不同的檔案。
-B 的檔案系統要求
-B 不是 jdupes 自己重新壓縮或搬運檔案內容。
它依賴作業系統和檔案系統提供的同區段去重或克隆介面。
官方手冊列出的支援物件包括:
- Btrfs;
- 啟用 reflink 特性的 XFS;
- Apple APFS。
具體能否工作還取決於核心、掛載環境、jdupes 編譯特性和檔案系統格式化引數。
對於 XFS,僅僅看到檔案系統類型是 XFS 還不夠;檔案系統建立時必須啟用 reflink 能力。
可以先檢視檔案系統類型:
|
|
XFS 可進一步檢視檔案系統資訊:
|
|
不要僅憑命令沒有明顯報錯,就認定所有重複資料都已經釋放。
如何驗證 CoW 去重結果
先確認檔案仍然擁有不同 inode:
|
|
如果兩個 inode 不同,這是預期現象。
但 stat 顯示的塊數不一定能直接、準確地表達共享區段。
不同檔案系統對共享塊統計方式可能不同。
還可以比較去重前後的檔案系統可用空間:
|
|
對於 Btrfs,可結合檔案系統專用工具觀察空間分配:
|
|
測試時應使用可丟棄的樣本,分別修改其中一個檔案,然後驗證另一個檔案的雜湊沒有變化。
-B 的侷限
CoW 去重並不等於“零成本”。
共享區段需要檔案系統維護引用關係。
後續寫入會觸發新塊分配,並可能產生額外碎片。
對高頻隨機寫入的資料、資料庫檔案或持續變化的虛擬磁碟,應先評估寫入放大和碎片影響。
快照也可能讓空間統計變得更復雜。
刪除一個目錄中的檔案後,共享塊若仍被另一個檔案或快照引用,就不會立即釋放。
如果你的重點是 Btrfs 和 NAS 場景,可繼續參考站內的 Btrfs + jdupes CoW 去重實踐。
-L --link-hard:讓多個路徑成為同一個檔案
基本命令如下:
|
|
-L 會把每組重複檔案中的其他副本替換為指向第一個檔案 inode 的硬連結。
處理完成後,多個路徑名稱仍然存在,但它們不再是獨立檔案。
硬連結後的結構
處理前:
|
|
處理後:
|
|
此時 a.bin 和 b.bin 是同一個 inode 的兩個目錄項目。
它們不只是“共享內容”,而是同一個檔案擁有兩個名字。
修改任一硬連結會發生什麼
如果程式直接開啟 b.bin 並覆蓋其中的位元組,a.bin 讀取到的內容也會改變。
因為兩條路徑最終訪問的是同一個 inode。
檔案權限、所有者和時間戳等 inode 中繼資料同樣不再彼此獨立。
但有一個容易混淆的例外:
有些編輯器並不是原地修改檔案,而是建立臨時檔案,再用重新命名替換原路徑。
這種“寫新檔案再替換”的儲存方式會讓被替換的路徑獲得新 inode,從而解除硬連結關係。
所以不能僅憑一次編輯測試,就推斷所有應用程式都具有相同行為。
硬連結不能跨檔案系統
硬連結只能在同一個檔案系統內建立。
即使兩個掛載點都使用 ext4,裝置或檔案系統執行個體不同,也不能跨越邊界建立硬連結。
可以用下面的命令檢視裝置號和 inode:
|
|
處理成功後,兩條路徑的裝置號和 inode 應當相同,連結計數通常會增加。
也可以使用:
|
|
刪除一個硬連結路徑不會立即刪除內容
刪除 b.bin 只是移除其中一個目錄項目。
只要 a.bin 仍然指向該 inode,檔案資料就仍然存在。
只有最後一個硬連結被刪除,並且沒有程序繼續開啟該檔案時,檔案系統才會回收相應物件和資料區塊。
這與符號連結的“目標路徑消失後留下斷鏈”完全不同。
什麼時候適合使用 -L
硬連結適合這些前提明確的場景:
- 檔案位於同一個檔案系統;
- 多個路徑在業務上確實可以視為同一個物件;
- 檔案預計只讀或內容不會再被原地修改;
- 備份、同步、索引和權限管理軟體能夠正確處理硬連結;
- 不需要每個路徑擁有獨立的 inode 中繼資料。
典型例子包括只讀套件快取、不可變歸檔副本和受控的媒體資源庫。
什麼時候不要使用 -L
以下情況應謹慎或避免使用:
- 某個副本可能被應用原地修改;
- 檔案分別屬於不同使用者或權限策略;
- 備份軟體可能把硬連結展開成多份資料;
- 同步軟體可能不保留硬連結關係;
- 應用依賴 inode 唯一性識別檔案;
- 檔案跨越多個檔案系統或網路掛載點。
如果兩個路徑現在內容相同,但未來職責不同,內容相同並不代表它們應該成為同一個 inode。
-l --link-soft:把副本替換為相對符號連結
基本命令如下:
|
|
-l 會保留每組中的第一個檔案,並把其他重複檔案替換為指向它的相對符號連結。
假設處理前有:
|
|
處理後第二個路徑可能表現為類似關係:
|
|
實際相對路徑由目錄位置決定。
相對符號連結意味著什麼
符號連結儲存的是目標路徑文字,而不是目標 inode 的額外名稱。
相對連結的解析起點是符號連結所在目錄,不是執行命令時的當前工作目錄。
因此,整體移動一棵內部結構不變的目錄樹時,相對符號連結通常仍能工作。
但是,只移動連結或只移動目標,就可能讓關係失效。
軟連結與硬連結的行為差異
軟連結可以跨檔案系統。
硬連結通常不能跨檔案系統。
軟連結擁有自己的檔案類型和 inode。
硬連結只是同一普通檔案 inode 的另一個名稱。
軟連結目標被刪除或改名後,連結可能變成斷鏈。
刪除一個硬連結名稱時,只要還有其他硬連結,內容仍然可訪問。
軟連結可以指向目錄;本文討論的 jdupes 動作針對重複檔案集合。
軟連結會改變檔案類型
執行 -l 以前,兩個路徑都是普通檔案。
執行以後,其中一個仍是普通檔案,其他路徑變成符號連結。
這會影響某些應用:
- 安全策略可能拒絕跟隨符號連結;
- 容器或沙箱可能看不到連結目標;
- Web 服務可能禁止訪問連結指向的路徑;
- 備份軟體可能只備份連結本身;
- 檔案監控程式可能對連結和目標產生不同事件;
- 權限檢查最終會落在目標路徑及其父目錄上。
所以,“檔案還能開啟”並不等於應用相容性已經驗證。
如何驗證軟連結
檢視連結儲存的目標文字:
|
|
解析最終目標:
|
|
檢查目錄樹中的斷鏈:
|
|
find -xtype l 會找出最終目標無法解析的符號連結。
在正式使用前,還應測試移動目標檔案、移動上級目錄、備份恢復和應用讀取等操作。
什麼時候適合使用 -l
軟連結適合“引用關係本來就合理”的場景:
- 希望顯式指定一個權威副本;
- 其他路徑本來就只是入口或相容路徑;
- 需要跨檔案系統引用;
- 應用明確支援符號連結;
- 能夠保證目標路徑的生命週期。
如果目錄樹經常被拆分、單獨同步或分別打包,軟連結通常不是理想選擇。
-d --delete:選擇保留項,刪除其餘副本
基本命令如下:
|
|
-d 會針對每組重複檔案提示使用者選擇要保留的路徑,然後刪除其餘路徑。
這是四種方式裡最直觀的一種,也是最不可逆的一種。
-B、-L 和 -l 都會在一定形式上保留原來的路徑入口。
-d 則真正移除未保留檔案的目錄項目。
刪除重複內容不等於沒有資訊損失
兩個檔案的內容完全相同,並不代表兩條路徑沒有各自價值。
不同路徑可能表達不同的:
- 目錄分類;
- 檔名語義;
- 所屬專案;
- 訪問控制上下文;
- 備份保留策略;
- 應用索引關係;
- 使用者工作流程。
jdupes 判斷的是檔案內容是否重複,不會替你判斷哪個目錄項目具有業務意義。
因此,刪除前需要同時審查內容和路徑。
最重要的風險一:不要重複指定同一個目錄
不要這樣執行:
|
|
也要避免透過不同寫法把同一棵目錄樹傳入兩次,例如:
|
|
官方文件警告:當同一個目錄被指定多次時,同一檔案可能以“自己的重複項”形式出現在集合中。
如果使用者在這種混亂的集合裡保留了一個顯示項,卻刪除了代表同一真實檔案的另一個顯示項,就可能造成資料丟失。
執行前應把所有輸入路徑規範化,並確認它們沒有重複、別名或意外重疊。
可以先檢查真實路徑:
|
|
還要留意 bind mount、符號連結目錄和容器對映是否讓同一內容從多個入口被走訪。
最重要的風險二:謹慎組合 -d 與 -s
-s 或 --symlinks 會跟隨符號連結目錄。
當它與 -d 同時使用時,互動列表可能同時出現符號連結相關路徑和被指向的真實檔案。
官方手冊指出,使用者可能誤保留符號連結,卻刪除它所指向的檔案。
結果就是看似保留了一個路徑,實際上只留下無法訪問目標的連結。
除非已經完整繪製並核對符號連結關係,否則不要使用:
|
|
更穩妥的做法是先不跟隨符號連結,分開檢查真實目錄和連結結構。
-N --no-prompt 會把刪除變成自動操作
-N 與 --delete 一起使用時,會自動保留每組的第一個檔案並刪除其餘檔案。
例如:
|
|
這不是普通的“跳過確認”,而是把“第一項是誰”直接變成保留策略。
若確實需要自動化,應先理解:
-o name預設按檔名排序;-o time可按修改時間排序;-i會反轉排序;-O --param-order會優先保留命令列引數順序對結果集合的影響。
自動刪除前,應在同樣的路徑、排序和遞迴選項下先執行只讀掃描,並儲存結果供審計。
對沒有可靠備份的資料,不建議直接使用 -d -N。
四種模式對權限和中繼資料的影響
預設情況下,jdupes 的核心目標是判斷內容重複。
但內容相同的檔案可能有不同的所有者、組或權限位。
-p --permissions 可以要求所有者、組和權限位不同的檔案不要被視為重複項:
|
|
這對 -L 尤其重要。
硬連結後多個路徑共享 inode 中繼資料,不可能繼續保持各自不同的屬主和權限位。
對 -d 來說,選擇保留哪一個路徑也會決定最終留下哪份檔案中繼資料。
對 -l 來說,訪問內容時最終受目標檔案和路徑遍歷權限控制。
對 -B 來說,檔案 inode 仍然獨立,因此各自的權限和大部分中繼資料可以繼續獨立存在。
如果還依賴 ACL、擴充屬性、SELinux 標籤或檔案能力,應使用對應工具額外核查。
僅比較傳統權限位,並不代表所有擴充中繼資料都已納入業務判斷。
跨檔案系統時怎麼選
掃描多個掛載點時,可以加入:
|
|
-1 --one-file-system 會阻止跨檔案系統或裝置匹配。
這能減少後續動作遇到能力邊界的機率。
四種模式在跨檔案系統方面的差異如下:
-B依賴檔案系統介面和共享區段能力,通常需要目標位於相容範圍內;-L無法建立跨檔案系統硬連結;-l可以儲存跨檔案系統的路徑引用,但目標掛載缺失時連結不可用;-d可以刪除不同檔案系統上的副本,但必須確認保留項所在儲存長期可用。
例如,把本地副本刪掉,只保留可拔行動硬碟或臨時網路掛載上的副本,技術上可能成功,業務上卻非常危險。
一套穩妥的執行流程
不要直接把動作選項加到生產目錄上。
建議按以下順序執行。
第一步:確認備份或快照可恢復
快照存在不代表一定可恢復。
至少確認:
- 快照覆蓋本次掃描的所有目錄;
- 快照建立時間早於去重動作;
- 快照不會與生產目錄共享同一故障域;
- 已知道恢復單個檔案和整個目錄的方法;
- 恢復操作經過抽樣測試。
硬連結和符號連結還需要確認備份工具是否保留連結語義。
第二步:確認輸入路徑沒有重複
列出準備掃描的每一個目錄:
|
|
檢查它們是否:
- 指向同一真實目錄;
- 一個目錄完整包含另一個目錄;
- 透過符號連結再次進入同一目錄樹;
- 透過 bind mount 或網路掛載出現別名;
- 因 shell 萬用字元展開而重複。
尤其在使用 -d 時,任何不清楚的重疊都應先消除。
第三步:先做只讀掃描
|
|
把輸出儲存到稽核檔案:
|
|
這裡沒有使用動作選項,因此只輸出匹配集合。
逐組檢查哪些路徑應該保留獨立語義,哪些只是冗餘副本。
第四步:在小型測試目錄驗證行為
建立一個可丟棄的測試目錄:
|
|
先檢視 inode 和雜湊:
|
|
然後每次只測試一種動作。
測試硬連結:
|
|
要測試其他動作,應重新建立乾淨樣本,不要在已經硬連結的檔案上繼續疊加測試。
第五步:一次只執行一種動作
不要把四種處理模式堆在同一條命令裡。
根據目錄職責拆分批次,例如:
|
|
|
|
|
|
|
|
這樣更容易解釋結果、驗證變化和執行恢復。
第六步:操作後驗證
無論選擇哪一種方式,都至少執行這些檢查:
|
|
|
|
|
|
再根據模式補充驗證:
-B:確認 inode 獨立,抽樣修改一個副本後另一個不變;-L:確認 inode 相同,連結計數正確;-l:用readlink和realpath確認目標,檢查斷鏈;-d:根據稽核清單確認該保留的路徑仍存在。
最後讓實際使用這些檔案的應用執行一次讀取、索引、備份或同步測試。
如何根據場景選擇
NAS 媒體庫和照片歸檔
如果底層是支援去重的 Btrfs,且檔案可能被照片管理或媒體管理程式修改,優先評估 -B。
它能保留獨立檔案語義,降低硬連結聯動修改的風險。
如果目錄完全只讀,而且應用能正確處理硬連結,-L 也可能有效。
套件快取和建置產物
不可變建置產物位於同一檔案系統時,-L 通常簡單高效。
但建置工具若會原地改寫快取檔案,就應避免硬連結。
能隨時重新生成的快取,也可以直接使用 -d,但仍要確認刪除不會破壞索引。
多版本備份目錄
多版本目錄需要每個版本保持獨立檢視。
支援 CoW 時,-B 通常比 -L 更符合這種語義。
硬連結也常用於增量備份,但必須由備份程式系統性管理,不能只憑“當前內容相同”臨時替換。
相容舊路徑
如果一個權威檔案需要從多箇舊路徑訪問,而且軟體支援符號連結,可以選擇 -l。
這相當於明確告訴系統:其他路徑只是引用。
目標路徑必須穩定,並且備份、容器和權限策略都要覆蓋它。
一次性清理下載目錄
確認重複副本沒有目錄語義,且備份可用時,可以用互動式 -d。
先只讀掃描,再逐組選擇保留項。
不要為了省幾次按鍵就立刻加入 -N。
常見誤區
誤區一:四種模式節省的空間完全一樣
不一定。
-d、-L 和 -l 最終只保留一份普通檔案內容,但仍有不同數量和類型的目錄項目或連結物件。
-B 的實際節省量取決於檔案系統成功共享的區段、塊大小、對齊、快照和後續寫入。
誤區二:硬連結是更可靠的軟連結
兩者語義不同,不能按“可靠程度”簡單排序。
硬連結把多個名稱繫結到同一 inode。
軟連結儲存一個可解析的目標路徑。
前者沒有“目標路徑被改名就斷鏈”的問題,後者則能跨檔案系統並明確表達引用關係。
誤區三:CoW 去重後兩個檔案就是硬連結
不是。
CoW 去重後的檔案仍有獨立 inode,只是共享部分或全部資料區塊。
硬連結則從 inode 層就是同一個檔案。
用 ls -li 或 stat 可以觀察這一差別。
誤區四:內容相同就可以安全刪除任意一個
內容相同只證明位元組相同。
路徑、檔名、權限、標籤、業務歸屬和備份策略仍可能不同。
-d 的選擇必須基於路徑語義,而不只是檔案內容。
誤區五:相對軟連結一定更便攜
相對連結只有在連結和目標保持相對位置時才便攜。
如果只複製其中一個子目錄,連結可能立即失效。
打包、同步和容器掛載都可能改變原有目錄關係。
誤區六:刪除後 df 一定立即增加可用空間
不一定。
檔案可能仍被程序開啟,也可能被快照、其他硬連結或 CoW 共享引用。
檔案系統延遲迴收和空間統計方式也會影響觀察結果。
參考資料
最終選擇建議
如果檔案系統支援 CoW,而且希望檔案以後還能獨立修改,-B --dedupe 通常是四種方案中語義最溫和的選擇。
如果明確需要多個路徑表示同一個不可變檔案,並且都在同一檔案系統,使用 -L --link-hard。
如果需要建立清晰的路徑引用關係,並能接受目標移動後斷鏈的風險,使用 -l --link-soft。
如果多餘路徑本身沒有任何保留價值,而且已經有可靠恢復手段,再使用 -d --delete。
無論選擇哪一種,都應遵循同一原則:
先只讀掃描,核對路徑,測試應用行為,再執行動作,最後驗證檔案系統和業務結果。
對 -d 再強調一次:不要重複指定同一目錄,也不要在沒有完整核對符號連結關係時與 -s 或 --symlinks 組合使用。
省下來的儲存空間可以重新購買,丟失的目錄語義和唯一副本卻未必能夠重建。