it-mot-dan-vi.com

Làm cách nào để chuyển danh sách tệp cho grep

Tôi đang sử dụng find và nhận danh sách các tệp tôi muốn grep thông qua. Làm cách nào để tôi chuyển danh sách đó thành grep?

105
MageProspero

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 dòng grep của bạn bằng backticks hoặc $(), 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ự lạ kỳ khác khác ((\'" cho xargs, \[*? cho $(find …)).


Tuy nhiên, trong trường hợp cụ thể của 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' {} \;

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 một grep riêng cho mỗi tệp; vì grep có 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 + để nói tìm chuyển tất cả tên tệp phù hợp thành grep cùng một lúc:

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

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

Nếu việc triển khai của bạn không có -R cờ hoặc nếu bạn muốn tiêu chí khớp tệp fancier, bạn có thể sử dụng -exec chính của find để thực hiện grep. Một vài triển khai find cũ hơn không hỗ trợ -exec Khác +; trên các hệ thống này, sử dụng dấu ; thay cho + (điều này sẽ gọi grep mộ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/null lừa để khiến 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ó -H tùy chọn để đạt được hiệu quả tương tự).

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