Find

使用 find 刪除除某個子目錄中的所有文件

  • June 10, 2020

我想遞歸刪除文件夾中一段時間內未訪問的所有文件,子文件夾a中的所有文件除外b

find a \( -name b -prune \) -o -type f -delete

但是,我收到一條錯誤消息:

find:-delete 操作自動打開 -depth,但 -prune 在 -depth 生效時不執行任何操作。如果您想繼續,只需明確使用 -depth 選項。

添加-depth會導致b包含所有文件,這不能發生。

任何人都知道使這項工作的安全方法嗎?

一種方法是使用-exec rm而不是-delete.

find a \( -name b -prune \) -o -type f -exec rm {} +

或者使用-not -path代替-prune

find a -not -path "*/b*" -type f -delete

解釋為什麼-prune與 碰撞-delete

當您嘗試使用-deletewith時 find 會抱怨,-prune因為-delete暗示-depth並使無效。-depth``-prune

觀察 find 有和沒有的行為-depth

$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2

不能保證單個目錄中的順序。但是可以保證目錄在其內容之前被處理。注意foo/any 之前foo/*foo/barany 之前foo/bar/*

這可以用 反轉-depth

$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/

注意現在都foo/*出現在之前foo/。與 相同foo/bar

更多解釋:

  • -prune防止 find 下降到目錄中。換句話說-prune,跳過目錄的內容。在您的情況下-name b -prune,這意味著當 find 到達具有該名稱的目錄時,b它將跳過該目錄,包括所有子目錄。
  • -depth使 find 在目錄本身之前處理目錄的內容。這意味著當 find 開始處理目錄條目時,b它的內容已經被處理了。因此在效果-prune上是無效-depth的。
  • -delete意味著-depth它可以先刪除內容,然後再刪除空目錄。-delete拒絕刪除非空目錄。

替代方法的說明:

find a -not -path "*/b*" -type f -delete

這可能更容易記住,也可能不容易記住。

該命令仍會進入目錄b並處理其中的每個文件,只是為了-not拒絕它們。b如果目錄很大,這可能是一個性能問題。

-path工作方式不同於-name. -name僅與(文件或目錄的)名稱-path匹配,而與整個路徑匹配。例如觀察路徑/home/lesmana/foo/bar-name bar將匹配,因為名稱是bar. -path "*/foo*"將匹配,因為字元串/foo在路徑中。-path在使用它之前,您應該了解一些複雜性。閱讀手冊頁以find獲取更多詳細資訊。

請注意,這不是 100% 萬無一失的。存在“誤報”的可能性。命令在上面寫入的方式將跳過任何具有名稱以b(正)開頭的父目錄的文件。但它也會跳過任何名稱以開頭的文件,b而不管樹中的位置如何(誤報)。這可以通過編寫比 更好的表達式來解決"*/b*"。這留給讀者作為練習。

我假設您使用aandb作為佔位符,而真實姓名更像是allosaurusand brachiosaurus。如果你把brachiosaurus它代替,b那麼誤報的數量將大大減少。

至少誤報不會被刪除,所以不會那麼慘。-delete此外,您可以通過首先執行不帶的命令(但請記住放置隱含的-depth)並檢查輸出來檢查誤報。

find a -not -path "*/b*" -type f -depth

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