rm命令弱爆了!

良許 發表於 2021-11-29

大家好,我是良許。

建立、刪除和修改檔案是使用者在 Linux 系統中執行的非常常見操作。大家都知道,在 Linux 系統裡使用 rm 命令刪除單個檔案時,幾乎一瞬間就完成了。但是如果檔案數量很大,那麼刪除操作就需要很長時間才能完成。

你有沒想過,刪除 50 萬個小檔案,需要花費多少時間?

我寫這篇文章的目的,是為了找出在 Linux 中刪除巨量檔案的最快方法。通過測試發現,rm 命令簡直弱爆了!

我們將從一些簡單的檔案刪除方法開始,然後比較不同方法完成檔案刪除任務的速度。看看哪種方式刪除速度最快。

rm命令弱爆了!

1. 檔案刪除的幾種方式

在 Linux 系統中刪除檔案,最常用的命令就是 rm 命令。這個命令相信大家都已經很熟悉了,我們來簡單回顧一些 rm 命令的例子。

$ rm -f testfile

-f 選項在上面的命令中,表示將在不要求確認的情況下強行刪除檔案。

$ rm -rf testdirectory

這個命令將刪除名為 testdirectory 的目錄以及該目錄中的所有內容(使用的 -r 選項是遞迴刪除檔案)。

而刪除目錄,我們還有另一個命令,那就是 rmdir ,但是它只有在目錄為空時才會刪除該目錄。

$ rmdir testdirectory

現在我們看看在 Linux 中刪除檔案的一些其它不同方法。

我最喜歡的方法之一是使用 find 命令,再進行刪除操作。find 命令是一個非常方便的工具,可用於根據檔案的型別、大小、建立日期、修改日期和更多不同的條件來搜尋檔案。

我們來看一個 find 命令使用 -exec 來呼叫 rm 命令的例子。

$ find /test -type f -exec rm {} \;

上述命令將刪除 /test 目錄中的所有檔案。首先 find 命令將查詢目錄中的所有檔案,然後對於每個搜尋結果,它會執行 rm 命令。

我們再看看可以與 find 命令一起使用的一些不同方法來刪除檔案。

$ find /test -mtime +7 -exec rm {} \;

在上述示例中,find 命令將搜尋 /test 目錄中 7 天前修改過的所有檔案,然後刪除每個檔案。

$ find /test -size +7M -exec rm {} \;

上述示例中,將搜尋目錄 /test 目錄中所有大於 7M 的檔案,然後再刪除它們。

在以上我們列出來的所有 find 命令示例中,都會為找到的每個檔案呼叫 rm 命令。例如,在上面的最後一個 find 命令中,如果結果中有 50 個大於 7M 的檔案,那麼將呼叫 50 次 rm 命令刪除檔案。而這樣的操作將需要花費更長的時間。

除了在 find 中藉助 -exec 引數呼叫 rm 命令外,還有一個更好的選擇,那就是使用 -delete 選項。比如:

$ find /test -size +7M -delete

達到的效果與上一條命令一樣。

2. 刪除巨量檔案時用什麼命令最快?

話不多說,我們直接上測試。

首先借助一個簡單的 bash for 迴圈建立 50 萬個檔案。

$ for i in $(seq 1 500000); do echo testing >> $i.txt; done

上述命令中,將在當前工作目錄中建立 50 萬個 txt 檔案,名稱從 1.txt 到 500000.txt,每個檔案都包含 testing 的文字內容,因此檔案大小至少在幾千位元組的範圍。

在建立了 50 萬個檔案後,我們將嘗試使用多方式來刪除它們,看看哪種方式刪除巨量檔案速度最快。

rm命令弱爆了!

Round 1:rm 命令

首先讓我們使用簡單的 rm 命令,同時我們使用 time 命令來計時。

$ time rm -f *
-bash: /bin/rm: Argument list too long
real    0m11.126s
user    0m9.673s
sys     0m1.278s

我們可以看到 rm 命令的執行結果是 Argument list too long ,這意味著該命令沒有完成刪除,因為給 rm 命令的檔案數量太大而無法完成,所以它直接就躺平罷工了。

不要注意 time 命令顯示的時間,因為 rm 命令沒有完成它的操作,time 命令只管顯示你命令執行了多長時間,而不關心命令的最終結果。

Round 2:使用 -exec 引數的 find 命令

現在讓我們使用我們之前看到的帶有 -exec 引數的 find 命令。

$ time find ./ -type f -exec rm {} \;
real    14m51.735s
user    2m24.330s
sys     9m48.743s

從我們使用 time 命令得到的輸出可以看出,從單個目錄中刪除 50 萬個檔案需要 14 分 51 秒。 這是相當長的時間,因為對於每個檔案,都會執行一個單獨的 rm 命令,直到刪除所有檔案。

Round 3:使用 -delete 引數的 find 命令

現在讓我們通過在 find 命令中使用 -delete 選項來測試消耗的時間。

$ time find ./ -type f -delete
real    5m11.937s
user    0m1.259s
sys     0m28.441s

刪除速度大大提高,只用了 5 分 11 秒!當你在 Linux 中刪除數百萬個檔案時,這是速度的驚人改進。

Round 4:Perl 語言

現在讓我們看看使用 Perl 語言刪除檔案是如何工作的,以及它與我們之前看到的其他刪除方式相比的速度。

$ time perl -e 'for(<*>){((stat)[9]<(unlink))}'
real    1m0.488s
user    0m7.023s
sys     0m27.403s

從結果可以看出,Perl 只用了大約 1 分鐘就刪除了該目錄中的 50 萬個檔案,與我們之前看到的其他 find 命令和 rm 命令相比,這個速度非常之快!

但是,如果您有興趣在使用 Perl 時用到更復雜的選項,則需要對 Perl 正規表示式有一定的瞭解。

rm命令弱爆了!

Round 5:rsync 命令

還有一種較少使用且鮮為人知的方法可用於刪除資料夾內的大量檔案,這種方法正是我們著名的工具 rsync ,它的基本用法是用於在 Linux 中的兩個本地和遠端位置之間傳輸和同步檔案。

現在我們來看看如何使用 rsync 命令的來刪除資料夾內所有檔案。其實很簡單,我們可以通過將具有大量檔案的目標目錄與空目錄進行同步來實現刪除的操作。

在我們的例子中, /test 目錄(目標目錄)有 50 萬個檔案,我們再建立一個名為 blanktest 的空目錄(源目錄)。現在,我們將在 rsync 命令中使用 -delete 選項,這將刪除目標目錄中的所有源目錄中不存在檔案。

$ time rsync -a --delete blanktest/ test/
real    2m52.502s
user    0m2.772s
sys     0m32.649s

可以看到,僅用 2 分鐘 52 秒就完成刪除。

因此與 find 命令相比,如果您想清空包含數百萬個檔案的目錄,使用 rsync 命令會更好。

3. 小結

下表總結了 Linux 中採用不同方式刪除 50 萬個檔案的速度,方便大家參考。

命令花費時間
rm 命令無法刪除大量檔案
使用 -exec 引數的 find 命令14 分 51 秒
使用 -delete 引數的 find 命令5 分 11 秒
Perl1 分鐘
rsync 命令2 分 52 秒

rm命令弱爆了!


最後,最近很多小夥伴找我要Linux學習路線圖,於是我根據自己的經驗,利用業餘時間熬夜肝了一個月,整理了一份電子書。無論你是面試還是自我提升,相信都會對你有幫助!

rm命令弱爆了!

免費送給大家,只求大家金指給我點個贊!

電子書 | Linux開發學習路線圖

也希望有小夥伴能加入我,把這份電子書做得更完美!

有收穫?希望老鐵們來個三連擊,給更多的人看到這篇文章

推薦閱讀:

歡迎關注我的部落格:良許Linux教程網,滿滿都是乾貨!