這裡介紹如何在 Linux 系統中使用 fdupes 這個指令找出重複內容的檔案,並且刪除之以節省硬碟空間。

電腦在使用一段時間之後,難免在硬碟中會有很多雜七雜八的檔案,為了節省硬碟空間,我們通常都會希望將重複的檔案刪除,然而要找出重複的檔案是非常費工又費時的。

在 Linux 中有一個 fdupes 指令,可以讓我們很方便的找出重複的檔案,並且刪除這些不必要的檔案,以下是使用方式。

安裝 fdupes

在 Ubuntu 等 Debian 系列的 Linux 中,可接用 apt 安裝:

sudo apt-get install fdupes

在 CentOS/RHEL 與 Fedora 中,可以使用 yum:

sudo yum install fdupes

從 Fedora 22 之後,則使用 dnf:

sudo dnf install fdupes

使用 fdupes

fdupes 在判斷檔案是否相同時,會按照以下的方式依序檢查:

  1. 檔案大小。
  2. 檔案部份內容的 MD5 檢查碼。
  3. 完整檔案的 MD5 檢查碼。
  4. 檔案內容。

也就是說 fdupes 在拿到兩個檔案時,會先比較兩個檔案的大小是否相同,如果檔案大小一模一樣的話,才繼續檢查後續的 MD5 檢查碼,若檢查到最後的檔案內容都全相同,則判定兩個檔案是重複的。

而如果兩個檔案在大小上就有差異的話,這兩個檔案的內容就一定不同,後續的 MD5 檢查碼與檔案內容就可以不需要檢查了,這樣可以加快檢查的速度。

產生測試用檔案

介紹 fdupes 的用法之前,先產生一些測試用的檔案:

for i in {1..5};   do date > file${i}.txt ; done
sleep 1
for i in {6..10};  do date > file${i}.txt ; done
sleep 1
for i in {11..15}; do date > file${i}.txt ; done

這裡我將 date 指令所輸出的日期導入檔案中產生測試用的檔案,這些檔案有很多會是相同的內容。

ls -l
total 60
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file1.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file10.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file11.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file12.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file13.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file14.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file15.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file2.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file3.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file4.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file5.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file6.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file7.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file8.txt
-rw-r--r-- 1 pi pi 29 Dec 28 10:43 file9.txt

接著我們就要使用 fdupes 把重複的檔案找出來。

列出重複的檔案

執行 fdupes 加上要檢查的目錄路徑,即可列出有重複的檔案列表:

fdupes /home/pi/fdupes/

輸出會像這樣:

/home/pi/fdupes/file9.txt               
/home/pi/fdupes/file10.txt
/home/pi/fdupes/file7.txt
/home/pi/fdupes/file8.txt
/home/pi/fdupes/file6.txt

/home/pi/fdupes/file11.txt
/home/pi/fdupes/file14.txt
/home/pi/fdupes/file12.txt
/home/pi/fdupes/file15.txt
/home/pi/fdupes/file13.txt

/home/pi/fdupes/file2.txt
/home/pi/fdupes/file1.txt
/home/pi/fdupes/file5.txt
/home/pi/fdupes/file4.txt
/home/pi/fdupes/file3.txt

加上 -S 參數可以輸出檔案的大小:

fdupes -S /home/pi/fdupes/
29 bytes each:                          
/home/pi/fdupes/file9.txt
/home/pi/fdupes/file10.txt
/home/pi/fdupes/file7.txt
/home/pi/fdupes/file8.txt
/home/pi/fdupes/file6.txt

29 bytes each:
/home/pi/fdupes/file11.txt
/home/pi/fdupes/file14.txt
/home/pi/fdupes/file12.txt
/home/pi/fdupes/file15.txt
/home/pi/fdupes/file13.txt

29 bytes each:
/home/pi/fdupes/file2.txt
/home/pi/fdupes/file1.txt
/home/pi/fdupes/file5.txt
/home/pi/fdupes/file4.txt
/home/pi/fdupes/file3.txt

如果要以遞迴的方式檢查該路徑所有子目錄下的檔案,可以加上 -r 參數:

fdupes -r /home/pi/

如果要搜尋比較大範圍的檔案時(例如整個家目錄),可能會找到許多系統用的隱藏檔,這些檔案雖然是重複的,但是多半不能隨便刪除,這時候可以加上 -A 參數排除隱藏檔:

fdupes -rA /home/pi/

也可以同時指定多個要檢查的路徑:

fdupes -rS /path/one/ /path/two/

加上 -m 參數可讓 fdupes 只輸出簡單的統計數字:

fdupes -rm /home/pi/
1481 duplicate files (in 589 sets), occupying 37.1 megabytes

刪除重複的檔案

通常找到重複的檔案之後,就是要把多餘的副本刪除,而刪除檔案有好幾種方式,最直接的就是加上 -d 參數:

fdupes -d /home/pi/fdupes/

這時候 fdupes 在找到重複的檔案時,就會詢問使用者要保留那一個檔案:

[1] /home/pi/fdupes/file9.txt           
[2] /home/pi/fdupes/file10.txt
[3] /home/pi/fdupes/file7.txt
[4] /home/pi/fdupes/file8.txt
[5] /home/pi/fdupes/file6.txt

Set 1 of 3, preserve files [1 - 5, all]:

使用者可以輸入想要保留的檔案編號,或是輸入 all 全部保留。

另一種方式是加上 -f 參數,讓 fdupes 將重複的檔案列表中,捨棄第一個找到的檔案,從二個重複的檔案開始列出來,也就是說這樣列出來的檔案是都可以直接刪除的:

fdupes -f /home/pi/fdupes/
/home/pi/fdupes/file10.txt              
/home/pi/fdupes/file7.txt
/home/pi/fdupes/file8.txt
/home/pi/fdupes/file6.txt

/home/pi/fdupes/file14.txt
/home/pi/fdupes/file12.txt
/home/pi/fdupes/file15.txt
/home/pi/fdupes/file13.txt

/home/pi/fdupes/file1.txt
/home/pi/fdupes/file5.txt
/home/pi/fdupes/file4.txt
/home/pi/fdupes/file3.txt

我們可以直接使用 rm 配合 xargs 來自動刪除這些重複的檔案:

fdupes -f /home/pi/fdupes/ | xargs rm -f

而比較保險的作法是建立一個垃圾桶目錄,將這些重複的檔案移到這個目錄中,等確認無誤後再把它們刪除:

mkdir trash_can
fdupes -f /home/pi/fdupes/ | xargs -I '{}' mv '{}' trash_can

然而這樣的作法就沒辦法選擇要保留那一個檔案了。

最後一種作法就是把重複的檔案列表導入檔案,人工檢查每一個檔案,手動刪除:

fdupes /home/pi/fdupes/ > dup.tx

參考資料:TecmintLinux.comHTG