題 在unix上清理當前目錄rm -r *


這是清理當前目錄的正確方法嗎?

rm -r * .

4
2017-07-13 11:59


起源




答案:


我通常只是在層次結構中向上移動一級,然後按名稱刪除目錄並重新創建它:

cd ..
rm -rf dirname
mkdir dirname
cd dirname

因為這消除了使用的錯誤情況 rm -rf * 在錯誤的目錄中。

注意: 如果目錄具有非標準權限或由某個其他帳戶擁有,則在刪除並重新創建目錄時將丟失該目錄。對我來說,這不是經常出現的事情,但值得思考。

如果我需要在腳本中執行此操作,我可能會創建一個函數來保存當前目錄,向上移動一個級別,刪除並創建新的空目錄,然後移動到那裡。


5
2017-07-13 16:43



+1它還消除了溢出命令行參數的可能性。 IIRC,cmd args只能有1k字節,所以 rm * 可能會擴展到更多。重新創建目錄恕我直言是最好的選擇(除非你有硬鏈接,但這只是骯髒的)。 - beatgammit
我不確定這種方法是否保證dirname創建時具有與刪除之前相同的權限/所有權,在刪除之前檢查該dirname可能是個好主意。 - AnonymousLurker
@AnonymousLurker,我確實提到了權限問題。這對我來說是90%的解決方案 - 我很少有具有奇數權限的目錄(至少與具有奇怪命名文件的目錄數相比)。 - Mark Bessey
@MarkBessey我建議你在答案中加入一個更明顯的警告(關於目錄的權限)。 - guntbert


不,並且有幾個原因:1)該命令將嘗試刪除 .,這是當前目錄,因此將失敗; 2)該命令不會刪除以“。”開頭的“隱藏”文件。字符; 3)該命令不會刪除目錄。

你可以用 rm -rf *。這將刪除所有文件和目錄,但不會刪除dotfiles。你可以用 find . -type f | xargs rm 刪除包括隱藏文件在內的所有文件,但這不會刪除目錄。

所以,你可以使用這個:

$ find . -print0 -type f -o -type d -not -name '\.' | xargs -0 rm -rf

在這裡,您遞歸地查找所有文件和目錄(只要它們不被稱為'。')然後刪除它們。該 -print0 和 -0 參數允許它正確處理名稱中帶有空格的文件名。


6
2017-07-13 12:14



此代碼不會刪除所有項目。試想一下名字中有空格的物品。所以更好用 -print0 同 find 和 -0 同 xargs。 - Shi
你是對的,謝謝。我編輯了它。
Unix與Linux有很大不同嗎?我可以用 rm --recursive * .*[^.]* 在Linux上,並想知道這是否適用於Unix。 - Paddy Landau
@PaddyLandau這不是對這個答案的評論,真的;這是一個單獨的問題。而“Unix”是一個非常廣泛的術語,涵蓋了從HP-UX和AIX到Mac OS X的所有內容。也就是說,它看起來像我那樣 rm 命令將刪除所有非點文件,以及包含至少一個非點字符的所有點文件。嘗試 touch ... (是的,三個時期),然後運行它。 - a CVn
@MichaelKjörling - 謝謝,但我提供了另一種選擇。我不確定它是否適用於Unix(我使用Linux),這就是我發布評論而不是單獨答案的原因。如果它適用於Linux,我認為這是一個簡單的答案。順便說一句, touch ... 確實創建了一個名為的隱藏文件 ... 在Linux中。 - Paddy Landau


如果-mindepth和-delete開關可用,則可以執行此操作:

find . -mindepth 1 -delete

如果你想堅持下去 POSIX,你可以做到這一點(如上所示) unix.com):

find . \( ! -name . -prune \) -exec rm -rf {} \+

2
2017-07-13 13:26





如果您不想使用find,一個簡單的解決方案是刪除當前目錄,然後重新創建它:

rm -rf "`pwd`" && mkdir "`pwd`" && cd "`pwd`"

1
2017-07-13 13:22



你可能想要緩存 pwd。刪除後我不確定這是否可以正常工作。 _dir=$(pwd) ; rm -rf "$_dir" && ...。雖然沒有測試過,所以我可能錯了。 - beatgammit


如果你正在使用bash(版本4或更高版本),你可以使用 dotglob shell選項包含以glob中的點開頭的文件名。

shopt -s dotglob
rm -r -- *

以上內容將打破包含數十萬個文件的目錄;在這種情況下,你可以使用 printf (作為內置的bash, 在ARG_MAX面前笑了)和 xargs (這將提供一個安全數量的參數 rm)。

shopt -s dotglob
printf '%q ' * | xargs rm -r --

你可以解開 dotglob 一旦你完成了:

shopt -u dotglob

另一種方法是在不搞亂shell選項的情況下執行此操作:

rm -r -- * .[^.]* ..?*
##  or
printf '%q ' * .[^.]* ..?* | xargs rm -r --

第一個水珠 * 將匹配當前目錄中不以點開頭的所有內容;第二個 .[^.]* 匹配以點開頭的所有內容,後跟一個非點字符,後跟任意數量的其他字符;第三個glob匹配兩個點,後跟任意一個字符,後跟任意數量的其他字符。如果你被困在沒有dotglob選項的shell中,這可能很有用;但是,在這種情況下 printf 可能不是內置的shell,或者可能缺少 %q flag(在引用它的參數中引用所有空格和異常字符,使它們安全傳遞給它 xargs),所以你應該使用其中之一 find在這種情況下的解決方案。


1
2017-07-13 13:52



如果您有一個巨大的目錄列表,由於CMD args的數量,這可能會失敗。 - beatgammit
@tjameson是的,雖然那必須是相當多的文件... - evilsoup
我上週在工作中碰到了這個問題。這是大約500,000個文件...... - beatgammit
@tjameson ......好吧,那麼,我會在免責聲明中編輯 - evilsoup