Trên Linux, làm cách nào tôi có thể tìm thấy tất cả các tệp có chứa một chuỗi và xóa chúng?


17

Tôi muốn xóa tất cả các tập tin có chứa chuỗi foo. Làm thế nào tôi có thể làm điều này bằng cách sử dụng bash trong Linux?


chuỗi đó là tên tập tin của nó?
rɑːdʒɑ

3
Vui lòng làm rõ: bạn có muốn xóa các tệp có tên chứa foo(ví dụ myfoo.jpg) hoặc các tệp chứa chuỗi byte foo(có thể bao gồm các tệp nhị phân xảy ra để chứa chuỗi byte đó) không?
hammar

Câu trả lời:


33

Đây là một cách an toàn:

grep -lrIZ foo . | xargs -0 rm -f --
  • -l in tên tệp của tệp phù hợp với mẫu tìm kiếm.
  • -rthực hiện tìm kiếm đệ quy cho mẫu footrong thư mục đã cho .. Nếu điều này không hiệu quả, hãy thử -R.
  • -I(viết hoa i) khiến các tệp nhị phân như PDF bị bỏ qua.
  • -Z đảm bảo rằng tên tệp bằng 0- (nghĩa là nul-) bị chấm dứt để tên chứa khoảng trắng không bị hiểu sai (nghĩa là nhiều tên thay vì một tên).
  • xargs -0cung cấp tên tệp từ grepđến rm -f, tách các từ bằng byte (nul) byte (nhớ -Ztùy chọn từ grep).
  • --thường bị lãng quên nhưng điều rất quan trọng là đánh dấu sự kết thúc của các tùy chọn và cho phép xóa các tệp có tên bắt đầu -.

Nếu bạn muốn xem tập tin nào sắp bị xóa, chỉ cần xóa | xargs -0 rm -f --phần đó và bỏ Ztùy chọn grep.

Một người dùng khác đã đề xuất một cái gì đó như sau, mà bạn không nên chạy vì nó không an toàn:

files=`grep foo * | cut -d: -f1`
rm -f $files         # unsafe, do not run it!

Nếu tôi có các tệp ImportantStuffmà tôi không muốn xóa và obsolete ImportantStuffchứa foo, thì tôi sẽ mất ImportantStuff(và không obsolete ImportantStuff !) Khi tôi chạy lệnh này, vì $filesbị phá vỡ tại các khoảng trắng khi nó được giải thích. Thật nguy hiểm khi đặt một danh sách tên tệp vào biến vỏ vô hướng theo cách này.


17
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;

Điều này đệ quy tìm kiếm các tập tin có chứa foo. Thứ hai -execchỉ được chạy nếu lần đầu tiên execthoát thành công, tức là nếu grepkhớp. Làm khô và loại bỏ echonếu đầu ra có vẻ đúng.

Hay cách khác

$ find -type f -exec grep -q "foo" {} \; -print

$ find -type f -exec grep -q "foo" {} \; -delete

theo đề xuất của Lekensteyn.


4
... có thể rút ngắn thành: find -type f -exec grep -q 'foo' {} \; -delete(các trích dẫn xung quanh {}là dư thừa, findcũng có thể xóa các tệp.). Lưu ý rằng grepchấp nhận một biểu thức chính quy. Nếu bạn muốn tìm kiếm foo.bar, hãy thoát khỏi điều này hoặc vượt qua -Ftùy chọn để coi mẫu là nghĩa đen.
Lekensteyn

bất kỳ lý do để sử dụng -exec echo rm "{}" \;và không -delete?
vartec

1
@vartec Không, tôi sẽ sử dụng -delete. Nó chỉ dễ dàng hơn để chứng minh với thứ hai -execvà tiếng vang tại chỗ.
Adrian Frühwirth

1
Nó dễ dàng hơn để gõ -print(hoặc -lscho nhiều chi tiết hơn) -exec echo rm "{}" \'. Không cần các tiện ích bên ngoài.
Lekensteyn

1
nếu bạn sử dụng rm {}, hãy sử dụng rm - {}, để bất kỳ ký tự đặc biệt nào trong tên tệp không bị nội suy. Ví dụ: chạm '-rf /' trong bất kỳ thư mục nào bạn có quyền ghi ...
atk

1

Tôi sẽ làm những gì Adrian nói,

Nhưng tôi sẽ thêm các ràng buộc từ vào trong foo để không vô tình xóa các tệp có chứa "thực phẩm" (trừ khi nó xóa mọi thứ có chứa thực phẩm là những gì bạn muốn.)

 $ find -type f -exec grep -q "\<foo\>" {} \; -delete

Về mặt thực tế, tôi sẽ chuyển hướng đầu ra trước khi xóa để tôi có thể xem lại trước khi xóa:

 $ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete

Ngay khi bạn có thể đăng bình luận, bạn nên đăng những thứ như thế dưới dạng bình luận.
FSMaxB

vâng tôi đã thử trước nhưng sau đó nhận ra rằng tôi chưa được phép đăng bình luận.
Petter H
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.