Tại sao find với -delete xóa các tệp trong thư mục / save / của tôi khi tìm mà không xóa không thể xác định vị trí của chúng?


20

Tôi muốn xóa tất cả các tệp trong cây thư mục hiện tại, ngoại trừ những tệp trong save. Tôi đã chạy lệnh này:

 find . \( -name save -prune \) -o -type f -ls | grep /save/

và nó không tìm thấy. Nhưng khi tôi chạy lệnh này:

 find . \( -name save -prune \) -o -type f -delete

Tất cả những tập tin trong / save / đã biến mất. Tôi đang thiếu gì?


4
Ouch ... tôi đã học được một cái gì đó ngày hôm nay (nhờ bạn). Và tôi khuyên bạn nên đơn giản mv save/ ../some/safer/locationtrước lệnh xóa "chung" như vậy (... nhưng tất nhiên, trước bài đăng của bạn, tôi đã thực hiện kiểm tra tương tự và gặp rắc rối tương tự!). Bây giờ, hãy tìm một "phục hồi" tốt cho hệ thống tệp mà các tệp đã được bật ^^
Olivier Dulac

3
Nỗi đau của tôi là phòng ngừa của bạn.
Otheus

1
1000 nhờ bạn. Mã (thường xuyên?) Hoạt động theo những cách bí ẩn ...
Olivier Dulac


@lesmana Tôi nêu lên câu trả lời của bạn đấy. thật đáng buồn, phiên bản tìm kiếm của tôi không cho tôi một lời cảnh báo hay như vậy :(
Otheus

Câu trả lời:


26

-deletengụ ý -depthrằng nó không hoạt động với -prune( -depthbắt đầu với những chiếc lá). Có một cảnh báo về điều đó trong hướng dẫn sử dụng phiên bản GNU ( -deletehiện là phần mở rộng FreeBSD cũng được GNU findvà một số triển khai khác hỗ trợ ).

info find --index-search=-delete

Việc sử dụng hành động '-delete' trên dòng lệnh sẽ tự động bật tùy chọn '-depth' (* lưu ý tìm Biểu thức: :). Điều này có thể gây ngạc nhiên nếu trước đây bạn chỉ thử nghiệm với '-print', vì vậy tốt nhất nên nhớ sử dụng '-depth' một cách rõ ràng.

info find --index-search=-prune

Bởi vì '-delete' ngụ ý '-depth', sử dụng '-prune' kết hợp với '-delete' có thể dẫn đến việc xóa nhiều tệp hơn bạn dự định.

Tại đây, bạn đã có tùy chọn sử dụng rmthay thế:

find . -name save -prune -o -type f -exec rm -f {} +

(có khả năng không an toàn nếu có thư mục có thể ghi bởi những người khác trong đó, vì người ta có thể khiến bạn xóa các tệp bên ngoài cây thư mục hiện tại bằng cách thay thế các thư mục bằng symlink trong khi bạn chạy lệnh đó).

Một sự thay thế an toàn hơn:

find . -name save -prune -o -type f -execdir rm -f -- {} \;

Điều đó không có vấn đề được đề cập ở trên nhưng có nghĩa là chạy một rmtệp cho mỗi tệp. Điều --này là cần thiết cho việc triển khai FreeBSD, không phải là GNU có tiền tố tên tệp ./.

Ngoài ra, theo đề xuất của Costas:

LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete

(nhưng điều đó vẫn không cần phải đi vào savethư mục)

Cái LC_ALL=Cnày *phù hợp với bất kỳ chuỗi byte nào (ngay cả những byte không tạo thành các ký tự hợp lệ trong miền địa phương hiện tại). Lưu ý rằng nó sẽ ảnh hưởng đến ngôn ngữ của thông báo lỗi (tiếng Anh thay vì ngôn ngữ của người dùng).


Vấn đề bảo mật ở đây là rmgì?
jrw32982 hỗ trợ Monica

@ jrw32982, xem chỉnh sửa với liên kết đến hướng dẫn tìm GNU
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.