Làm thế nào để tôi chuyển một danh sách các tập tin cho grep


98

Tôi đang sử dụng findvà nhận được một danh sách các tập tin tôi muốn grepthông qua. Làm thế nào để tôi dẫn danh sách đó đến grep?

Câu trả lời:


116

Chà, trường hợp chung hoạt động với bất kỳ lệnh nào ghi vào thiết bị xuất chuẩn là sử dụng xargs, điều này sẽ cho phép bạn đính kèm bất kỳ số lượng đối số dòng lệnh nào vào cuối lệnh:

$ find … | xargs grep 'search'

Hoặc để nhúng lệnh trong grepdòng của bạn bằng backticks hoặc $(), nó sẽ chạy lệnh và thay thế đầu ra của nó:

$ grep 'search' $(find …)

Lưu ý rằng các lệnh này không hoạt động nếu tên tệp chứa khoảng trắng hoặc một số ký tự kỳ lạ khác của Wikipedia ( \'"đối với xargs, \[*?for $(find …)).


Tuy nhiên, trong trường hợp cụ thể find, khả năng thực thi chương trình trên các đối số đã cho được tích hợp sẵn:

$ find … -exec grep 'search' {} \;

Tất cả mọi thứ giữa -exec;là lệnh để thực thi; {}được thay thế bằng tên tệp được tìm thấy bởi find. Điều đó sẽ thực thi riêng grepcho từng tệp; vì grepcó thể lấy nhiều tên tệp và tìm kiếm tất cả, bạn có thể thay đổi thành ;để +tìm tìm để chuyển tất cả tên tệp phù hợp thành grepcùng một lúc:

$ find … -exec grep 'search' {} \+

1
Cần lưu ý rằng hai hình thức đầu tiên không hoạt động với tên tệp chứa khoảng trắng.
enzotib

1
Tôi thích find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. QED. Mặc dù -exec +rất hiệu quả, nó không tồn tại trên tất cả các phiên bản tìm kiếm.
Arcege

Đáng buồn là tôi không thể kiểm tra bạn đúng 3 lần.
Arcabard

3
Tôi đề nghị sử dụng -exec, chứ không phải là xargs. Nếu bạn sử dụng -execin find, nó sẽ chỉ tạo một shell để grep cho nội dung. Nếu bạn sử dụng xargs, nó sẽ tạo ra hai shell: một cho cái kia findvà cái kia cho xargs.

2
bằng thực nghiệm tôi thấy rằng các $ find … -exec grep 'search' {} \+hình thức là nhiều nhanh nhất.
gogoud

9

Một số phiên bản grep(ví dụ: trên Linux hoặc BSD hoặc Mac OS X không nhúng ) có -rtùy chọn để thực hiện tìm kiếm đệ quy. Trên OpenBSD, sử dụng -R(và không có --excludenhư trong ví dụ bên dưới). Điều này bao gồm các kết hợp đơn giản findvới grep.

Nếu việc triển khai của bạn không có -Rcờ hoặc nếu bạn muốn các tiêu chí khớp với tệp fancier, bạn có thể sử dụng -execchính findđể thực hiện nó grep. Một vài cũ findtriển khai không hỗ trợ -exec... +; trên các hệ thống này, hãy sử dụng ;thay vì +(điều này sẽ gọi grepmột lần cho mỗi tệp, vì vậy nó sẽ chậm hơn, nhưng nếu không thì kết quả sẽ giống nhau). Lưu ý /dev/nullmẹo để gây ra grepđể hiển thị tên tệp ngay cả khi nó được gọi trên một tệp duy nhất (GNU grep và FreeBSD / NetBSD / OSX grep có -Htùy chọn để đạt được hiệu ứng tương tự).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .

2
GNU grep-Htùy chọn để luôn luôn in tên tệp.
enzotib
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.