使用 find 刪除除某個子目錄中的所有文件
我想遞歸刪除文件夾中一段時間內未訪問的所有文件,子文件夾
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
:當您嘗試使用
-delete
with時 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/bar
any 之前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*"
。這留給讀者作為練習。我假設您使用
a
andb
作為佔位符,而真實姓名更像是allosaurus
andbrachiosaurus
。如果你把brachiosaurus
它代替,b
那麼誤報的數量將大大減少。至少誤報不會被刪除,所以不會那麼慘。
-delete
此外,您可以通過首先執行不帶的命令(但請記住放置隱含的-depth
)並檢查輸出來檢查誤報。find a -not -path "*/b*" -type f -depth