TL; DR: cách tốt nhất là sử dụng -exec rmthay vì -delete.
find a \( -name b -prune \) -o -type f -exec rm {} +
Giải trình:
Tại sao tìm thấy phàn nàn khi bạn cố gắng sử dụng -deletevới -prune?
Câu trả lời ngắn: bởi vì -deletengụ ý -depthvà -depthlàm cho -prunekhông hiệu quả.
Trước khi chúng ta đi đến câu trả lời dài, trước tiên hãy quan sát hành vi tìm và không có -depth:
$ find foo/
foo/
foo/f1
foo/bar
foo/bar/b2
foo/bar/b1
foo/f2
Không có gì đảm bảo về thứ tự trong một thư mục. Nhưng có một đảm bảo rằng một thư mục được xử lý trước nội dung của nó. Lưu ý foo/trước bất kỳ foo/*và foo/bartrước bất kỳ foo/bar/*.
Điều này có thể được đảo ngược với -depth.
$ find foo/ -depth
foo/f2
foo/bar/b2
foo/bar/b1
foo/bar
foo/f1
foo/
Lưu ý rằng bây giờ tất cả foo/*xuất hiện trước foo/. Tương tự với foo/bar.
Câu trả lời dài hơn:
-prunengăn chặn tìm thấy từ giảm dần vào một thư mục. Nói cách khác -prunebỏ qua nội dung của thư mục. Trong trường hợp của bạn -name b -prunengăn không cho tìm thấy giảm dần vào bất kỳ thư mục có tên b.
-depthtìm để xử lý nội dung của một thư mục trước chính thư mục đó. Điều đó có nghĩa là theo thời gian tìm được để xử lý mục nhập thư mục bnội dung của nó đã được xử lý. Do đó -prunelà không hiệu quả với có -depthhiệu lực.
-deletengụ ý -depthđể nó có thể xóa các tập tin đầu tiên và sau đó là thư mục trống. -deletetừ chối xóa các thư mục không trống. Tôi đoán có thể thêm một tùy chọn để buộc -deletexóa các thư mục không trống và / hoặc để ngăn chặn -deletengụ ý -depth. Nhưng đó là một câu truyện khác.
Có một cách khác để đạt được những gì bạn muốn:
find a -not -path "*/b*" -type f -delete
Điều này có thể hoặc có thể không dễ nhớ hơn.
Lệnh này vẫn đi vào thư mục bvà xử lý mọi tệp duy nhất trong đó chỉ -notđể từ chối chúng. Đây có thể là một vấn đề hiệu suất nếu thư mục brất lớn.
-pathhoạt động khác hơn -name. -namechỉ khớp với tên (của tệp hoặc thư mục) trong khi -pathkhớp với toàn bộ đường dẫn. Ví dụ quan sát đường dẫn /home/lesmana/foo/bar. -name -barsẽ phù hợp vì tên là bar. -path "*/foo*"sẽ khớp bởi vì chuỗi /foonằm trong đường dẫn. -pathcó một số điều phức tạp bạn nên hiểu trước khi sử dụng nó. Đọc trang người đàn ông findđể biết thêm chi tiết.
Coi chừng rằng điều này không phải là 100%. Có nhiều khả năng "dương tính giả". Cách lệnh được viết ở trên nó sẽ bỏ qua bất kỳ tệp nào có bất kỳ thư mục mẹ nào có tên bắt đầu bằng b(positive). Nhưng nó cũng sẽ bỏ qua bất kỳ tập tin nào tên bắt đầu với bbất kể vị trí trong cây (dương tính giả). Điều này có thể được sửa chữa bằng cách viết một biểu thức tốt hơn "*/b*". Điều đó được để lại như một bài tập cho người đọc.
Tôi giả sử rằng bạn đã sử dụng avà blà người giữ chỗ và tên thật giống allosaurusvà hơn brachiosaurus. Nếu bạn brachiosaurusthay thế bthì số lượng dương tính giả sẽ giảm đáng kể.
Ít nhất là các dương tính giả sẽ không bị xóa, vì vậy nó sẽ không bi thảm như vậy. Hơn nữa, bạn có thể kiểm tra dương tính giả bằng cách trước tiên chạy lệnh mà không -delete(nhưng nhớ đặt hàm ý -depth) và kiểm tra đầu ra.
find a -not -path "*/b*" -type f -depth
angoại trừa/b?