2012-07-01 7 views
10

Tôi muốn tìm các tệp không chứa một chuỗi cụ thể (trong một thư mục và các thư mục con của nó) và xóa các tệp đó. Làm thế nào tôi có thể làm điều này?Xóa các tệp không chứa một chuỗi cụ thể

+0

xóa nghĩa là loại trừ. Đúng? –

+2

@SivaCharan yeah ... từ sự tồn tại :) –

+0

Bằng cách xóa ý tôi là: xóa – Hakim

Trả lời

0

Một khả năng là

find . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \; 

Bạn có thể loại bỏ các echo nếu xem trước này có vẻ đúng.

+1

chắc chắn bạn có nghĩa là 'grep -v'? – rodion

+0

Công trình này, +1. –

+0

Điều này không hiệu quả đối với tôi. Tôi có thể thấy lệnh rm đang chạy trong dòng lệnh, nhưng không có gì bị xóa sau khi hoàn thành lệnh. Tất cả các tệp đều tồn tại. Tôi đã kiểm tra thủ công các tệp và thấy rằng một số tệp không chứa chuỗi ... – Hakim

-1

EDIT: Đây là cách bạn NÊN KHÔNG làm điều này! Lý do được đưa ra here. Nhờ @ormaaj để chỉ nó ra!

find . -type f | grep -v "exclude string" | xargs rm 

Lưu ý: grep mẫu sẽ phù hợp với đường dẫn tập tin đầy đủ từ thư mục hiện hành (xem find . -type f đầu ra)

+1

Downvote không phải là tôi, nhưng FYI, nó có thể là do [xargs] (http://mywiki.wooledge.org/UsingFind#Actions_in_bulk:_xargs .2C_-print0_and_-exec_.2B-) – ormaaj

+0

@ormaaj OMG! Tôi sử dụng để sử dụng khá thường xuyên (xx;) Cảm ơn bạn đã chỉ ra nó. – rodion

5

GNU grep và bash.

grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done 

Sử dụng giải pháp find nếu tính di động là cần thiết. Điều này là hơi nhanh hơn.

+0

@ Peter.O Lạ thật, tôi không thể tái tạo điều đó. Nó xuất hiện nếu sử dụng '-r' nó không có sự lựa chọn nào khác ngoài mặc định cho các tập tin trừ khi' -' được đưa ra một cách rõ ràng. Tuy nhiên, '.' có lẽ là một ý tưởng hay. Đã thêm nó. – ormaaj

+0

Tôi đã xóa nhận xét ban đầu của mình khi bạn thêm '.', như bạn không nghi ngờ gì, nhưng tôi cũng hơi bối rối, vì 'man grep' hiển thị' [FILE ...] 'cho lần cuối cùng tùy chọn ... nhưng đó chắc chắn là những gì xảy ra ở đây (ví dụ: chờ đầu vào, không có '.'); * GNU grep 2.5.4 * –

+1

Giá trị mặc định "." cho grep -r được thêm vào grep 2.11, khá gần đây. Và GNU không tôn trọng trang người đàn ông nhiều. –

1

Tôi có thể nghĩ ra một số cách để tiếp cận vấn đề này. Dưới đây là một: tìm và grep để tạo danh sách các tệp không khớp, sau đó xargs rm chúng.

find yourdir -type f -exec grep -F -L 'yourstring' '{}' + | xargs -d '\n' rm 

Giả định công cụ GNU (grep -L và xargs -d không thể di chuyển) và tất nhiên không có tên tệp có dòng mới trong đó. Nó có lợi thế là không chạy grep và rm một lần cho mỗi tập tin, do đó, nó sẽ được hợp lý nhanh chóng. Tôi khuyên bạn nên thử nghiệm nó với "echo" thay cho "rm" chỉ để đảm bảo nó chọn đúng tệp trước khi bạn giải phóng sự hủy diệt.

+3

Điều này không thực hiện [xargs] (http://mywiki.wooledge.org/UsingFind#Actions_in_bulk:_xargs.2C_-print0_and_-exec_.2B-). Nếu sử dụng xargs, '-0' là cách duy nhất. – ormaaj

+0

-d '\ n' là một cách đủ tốt cho đến khi bạn nhận được một tên tập tin với một dòng mới trong đó. Nó vô hiệu hóa hầu hết các ngu xuẩn xargs, như -0. Rất tốt để tìm hiểu về grep -Z mặc dù. –

+1

tên tệp có dòng mới trong đó? làm thế nào về anh chàng với một con mèo trên bàn phím? Anh ta không thể gõ lệnh dài như thế này được! ar ya, thật điên rồ. nhưng bạn có thể tìm thấy trên youtube. –

6

Sau đây sẽ làm việc:

find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm 

này trước hết sẽ sử dụng tìm để in tên của tất cả các tập tin trong thư mục hiện hành và bất kỳ thư mục con. Những tên được in với một terminator rỗng chứ không phải là tách xuống dòng thông thường (thử đường ống đầu ra để od -c để xem hiệu quả của các đối số -print0.

Sau đó --null tham số để xargs nói với nó để chấp nhận đầu vào null-chấm dứt. xargs sau đó sẽ gọi grep vào một danh sách các tên tập tin.

các -Z lập luận để grep công trình như lập luận -print0 để find, vì vậy grep sẽ in ra kết quả của nó null-chấm dứt (đó là lý do cuộc gọi cuối cùng để xargs cần một lựa chọn --null quá.) -L lập luận để grep gây grep để in tên tập tin của các tập tin trên dòng lệnh của nó (mà xargs đã bổ sung) mà không trận đấu biểu thức chính quy:

chuỗi của tôi

Nếu bạn muốn khớp đơn giản mà không có ma thuật biểu thức chính quy, sau đó thêm tùy chọn -F.Nếu bạn muốn biểu thức chính quy mạnh hơn thì hãy đưa ra đối số -E. Đó là một thói quen tốt để sử dụng dấu nháy đơn chứ không phải dấu ngoặc kép vì điều này bảo vệ bạn chống lại bất kỳ ma thuật vỏ nào được áp dụng cho chuỗi (chẳng hạn như thay thế biến)

một lần nữa để loại bỏ tất cả các tệp mà bạn ' đã tìm thấy với các cuộc gọi trước đó.

Vấn đề với gọi grep trực tiếp từ lệnh find với lập luận -execgrep sau đó được gọi một lần cho mỗi tập tin chứ không phải là một lần cho một lô toàn bộ các tập tin như xargs làm. Đây là nhiều nhanh hơn nếu bạn có nhiều tệp. Cũng đừng bị cám dỗ để làm công cụ như:

rm $(some command that produces lots of filenames) 

Đó là luôn luôn tốt hơn để vượt qua nó để xargs như này biết những giới hạn dòng lệnh tối đa và sẽ gọi rm mỗi lần nhiều lần với nhiều lý lẽ như nó có thể .

Lưu ý rằng giải pháp này sẽ đơn giản hơn mà không cần phải đối phó với các tệp có chứa khoảng trắng và dòng mới.

Ngoài ra

grep -r -L -Z 'my string' . | xargs --null rm 

sẽ làm việc quá (và ngắn hơn). Đối số -r đến grep khiến nó đọc tất cả các tệp trong thư mục và đệ quy xuống bất kỳ thư mục con nào). Sử dụng phương pháp find ... nếu bạn muốn thực hiện một số thử nghiệm khác trên các tệp (chẳng hạn như độ tuổi hoặc quyền).

Lưu ý rằng bất kỳ đối số chữ cái nào, với một người giới thiệu đơn lẻ, có thể được nhóm lại với nhau (ví dụ như -rLZ). Nhưng cũng lưu ý rằng find không sử dụng cùng một quy ước và có đối số nhiều chữ được giới thiệu với một dấu gạch ngang. Đây là lý do lịch sử và chưa bao giờ được khắc phục bởi vì nó có thể đã phá vỡ quá nhiều tập lệnh.

+0

Giải thích tuyệt vời! –