Find

‘find -empty -delete’ 刪除非空目錄

  • June 19, 2021

如果我創建以下目錄結構:

mkdir -p dir1/dir2/dir3/dir4

然後我執行find dir1,它返回:

dir1
dir1/dir2
dir1/dir2/dir3
dir1/dir2/dir3/dir4

如果我執行find dir1 -empty,它只返回:

dir1/dir2/dir3/dir4

顯示只有 dir4 是空的。

但是,如果我執行find dir1 -empty -delete,所有四個目錄都會立即被刪除。

我希望只刪除 dir4,然後下次執行命令時,只會刪除 dir3,依此類推。為什麼會發生這種情況,我怎樣才能只刪除 dir4 使用find

因為-delete蘊含-depth或深度優先迭代,所以find首先查看dir1/dir2/dir3/dir4,發現它是空的,刪除它,然後查看dir1/dir2/dir3,發現它(現在)是空的並刪除它……

GNU 聯機幫助頁說:

-depth

在目錄本身之前處理每個目錄的內容。動作-delete也暗示。-depth

這可能是他們認為能夠刪除一些文件,然後可能是包含這些文件的目錄,如果它同時被清空(-delete不會遞歸刪除整個子樹),而不是必須重複find命令直到所有匹配的文件和目錄都消失了。或者換個角度看,只刪除樹的葉子(正如我們在這裡想要的那樣)不是冪等的:意外再次執行該命令會從目錄樹中刪除另一層。

在任何情況下,您都可以改為find執行rmdir以保持預設模式,並添加-prune以防止它嘗試下降到現在已刪除的目錄。讓我們在這裡也添加-print調試,所以我們看看它刪除了什麼:

$ mkdir -p dir1/dir2/dir3/dir4
$ find -type d -empty -exec rmdir {} \; -prune -print
./dir1/dir2/dir3/dir4

這就是剩下的:

$ find
.
./dir1
./dir1/dir2
./dir1/dir2/dir3

(在這裡,如果rmdir失敗,則-exec操作評估為虛假,並且-pruneand-print操作將不會執行。因此到 stdout 的列印輸出應僅包含實際刪除的內容。這與 .) 不同-exec rmdir {} +。)

當然,假設您只想在這裡刪除空目錄,如果您還想刪除空文件,您可以先這樣做

find -type f -empty -delete

或者建構呼叫rm文件和rmdir目錄的糟糕組合:

find -empty \( -type f -exec rm {} \; -o -type d -exec rmdir {} \; -prune \) -print

rm -rf顯然也可以,但風險更大。)

引用自:https://unix.stackexchange.com/questions/654922