Làm cách nào để xóa đệ quy các thư mục bằng ký tự đại diện?


51

Tôi đang làm việc thông qua SSH trên phiên bản WD My Book World. Về cơ bản tôi muốn bắt đầu ở một cấp độ thư mục cụ thể và loại bỏ đệ quy tất cả các thư mục con phù hợp .Apple*. Làm thế nào tôi sẽ đi về điều đó?

Tôi đã thử

rm -rf .Apple*rm -fR .Apple*

không xóa thư mục phù hợp với tên đó trong thư mục con.

Câu trả lời:


73

find rất hữu ích để thực hiện có chọn lọc các hành động trên toàn bộ cây.

find . -type f -name ".Apple*" -delete

Ở đây, -type fđảm bảo đó là một tệp, không phải là một thư mục và có thể không chính xác như bạn muốn vì nó cũng sẽ bỏ qua các liên kết tượng trưng, ​​ổ cắm và những thứ khác. Bạn có thể sử dụng ! -type d, nghĩa đen không phải là thư mục, nhưng sau đó bạn cũng có thể xóa các thiết bị ký tự và chặn. Tôi đề nghị nhìn vào -typevị ngữ trên trang man cho find.

Để làm điều đó một cách nghiêm ngặt với ký tự đại diện, bạn cần hỗ trợ shell nâng cao. Bash v4 có globstartùy chọn , cho phép bạn kết hợp đệ quy các thư mục con bằng cách sử dụng **. zshkshcũng hỗ trợ mô hình này. Sử dụng điều đó, bạn có thể làm rm -rf **/.Apple*. Đây không phải là tiêu chuẩn POSIX và không dễ mang theo, vì vậy tôi sẽ tránh sử dụng nó trong tập lệnh, nhưng đối với hành động shell tương tác một lần, nó vẫn ổn.


3
Tôi có thể find . -type d -name .Apple*làm việc - nó liệt kê tất cả các thư mục. Tuy nhiên, nó thất bại khi tôi thêm -deletevào cuối. Nó chỉ trở lại với bản tóm tắt sử dụng. Nó đang chạy trên BusyBox v1.1.1. Điều đó làm cho một sự khác biệt?
mã hóa

1
-deletecũng không phải là POSIX. **được giới thiệu zshvào đầu những năm 90. Bây giờ (theo thứ tự thời gian xuất hiện) cũng ở ksh93, cá, bash và tcsh.
Stéphane Chazelas

1
+1 chorm -rf **/.Apple*
Andriy Boyko

1
@codingog, nếu -deletekhông sử dụng công việc -exec rm -f {} +thay thế.
tự đại diện

1
Bạn có thể nhận findđược dài dòng khi nó xóa? Tôi cho rằng phương pháp "globalstar" sẽ làm điều này bằng cách thêm công -vtắc.
Demis

16

Tôi chạy vào vấn đề sử dụng findvới -deletedo hành vi cố ý của find(tức là từ chối xóa nếu con đường bắt đầu với ./, mà họ làm trong trường hợp của tôi) như đã nêu trong trang người đàn ông của mình:

 -delete

Xóa các tập tin và / hoặc thư mục tìm thấy. Luôn luôn trả lại đúng sự thật. Điều này thực thi từ thư mục làm việc hiện tại khi tìm thấy đệ quy xuống cây. Nó sẽ không cố xóa tên tệp có ký tự "/" trong tên đường dẫn của nó so với "." vì lý do bảo mật.
Xử lý truyền tải chiều sâu đầu tiên được ngụ ý bởi tùy chọn này.
Các liên kết sau không tương thích với tùy chọn này.

Thay vào đó, tôi đã có thể làm

find . -type d -name 'received_*_output' -exec rm -r {} +

Đối với trường hợp của bạn, có vẻ như trích dẫn toàn cầu (dấu hoa thị, *) là giải pháp, nhưng tôi muốn cung cấp câu trả lời của mình trong trường hợp bất kỳ ai khác có vấn đề tương tự.

LƯU Ý: Trước đây, câu trả lời của tôi là làm như sau, nhưng @Wildcard đã chỉ ra các lỗ hổng bảo mật khi thực hiện điều đó trong các bình luận.

find . -type d -name 'received_*_output' | xargs rm -r

1
Không có lý do chính đáng để sử dụng xargsở đây. -exec rm -r {} \;hoặc, tốt hơn, -exec rm -r {} +sẽ làm tốt mà không thất bại với tên tập tin nhân vật đặc biệt. Xem tại sao lặp đi lặp lại tìm kiếm thực tiễn xấu?
tự đại diện

Đó là điều tốt để biết. IMO không đáng để downvote, vì lệnh vẫn hoàn thành công việc, nhưng tối ưu hóa hiệu suất được đánh giá cao.
Pat

1
Nếu đó chỉ là một tối ưu hóa hiệu suất, tôi sẽ đồng ý với bạn, nhưng không phải vậy. Đó là một lỗ hổng bảo mật. Bạn không xử lý chính xác các tệp có khoảng trắng trong tên của chúng và tên tệp được tạo độc hại sẽ dẫn đến mất dữ liệu. Đồng thời xem hàm ý Bảo mật của việc quên trích dẫn một biến trong shell bash / POSIX ; một số trong số đó có thể áp dụng và ít nhất nó có thể cung cấp cho bạn một số ý tưởng về loại vấn đề tôi đang nói đến.
tự đại diện

Hãy thử mkdir -p $'blah\nDocuments\n/etc\n/home\n/received__output'trong thư mục của bạn và sau đó chạy lại lệnh tương tự, nếu bạn không tin rằng có khả năng mất dữ liệu. Hoặc, vì câu hỏi là về Mac OS , mkdir -p $'blah\nDocuments\n/Users\n/Applications\n/received__output'. ( Cảnh báo: Bạn S remove xóa tất cả các tệp của mình nếu bạn làm điều này. Đó là quan điểm của tôi.)
Wildcard

0

Điều có thể là không có gì sai với lệnh rm / find của bạn, nhưng người dùng mà bạn đã đăng nhập không thực sự có quyền xóa. Sử dụng ls -lđể liệt kê mọi thứ với quyền của họ và bạn có thể xác định bạn là ai với các lệnh idgroups(nên có sẵn). Nếu bạn là "người dùng sai" để làm điều này, bạn sẽ cần thay đổi quyền / quyền sở hữu các tệp hoặc chuyển sang người dùng khác.


0

Thử:

shopt -s dotglob           # using Bash
printf '%s\n' ./.Apple*    # test
#rm -rf ./.Apple*    

1
dotgloblà vô dụng ở đây. Xem trang này để biết ví dụ về những gì dotglob làm.
amphetamachine

-1

Lệnh đơn giản:

rm `find ./ -name '.Apple*'` -rf

Chúc may mắn!


4
Điều này cực kỳ dễ bị lỗi, tìm có khóa -exec.
Anton Barkovsky
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.