Grep đệ quy cho các từ trong một loại tệp cụ thể


7

Tôi muốn một lệnh dòng lệnh để tìm kiếm tất cả các tập lệnh shell trong hệ thống tập tin cho một từ cụ thể, vì vậy tôi đã hỏi xung quanh tại nơi làm việc và nhận được các giải pháp sau:

grep word `find / -name \*.sh 2>/dev/null`
find / -name "*.sh" 2>/dev/null | xargs grep word

Tuy nhiên, tôi không quen thuộc với dòng lệnh, vì vậy cả hai giải pháp này đều có vẻ mờ đục đối với tôi. Tôi muốn làm một cái gì đó trông giống như:

ls -r *.sh | cat | grep -H word

Nhưng có vẻ như bạn không thể đặt tên tập tin thành mèo (ít nhất tôi nghĩ đó là vấn đề).

Giải pháp dễ đọc nhất là gì? Và thứ hai, giải pháp hiệu quả nhất là gì?

Chỉnh sửa: Tôi cần biết từ nào được tìm thấy trong tập tin, vì vậy tôi có thể sửa đổi tập lệnh.

Câu trả lời:


8

Chỉnh sửa: Nếu bạn có các tiện ích GNU, hãy xem câu trả lời của Gilles cho một phương thức sử dụng grepcác khả năng đệ quy của GNU đơn giản hơn nhiều so với findcách tiếp cận. Nếu bạn chỉ muốn hiển thị tên tệp, bạn vẫn sẽ muốn thêm -ltùy chọn như tôi mô tả bên dưới.


Sử dụng grep -l wordđể chỉ in tên của các tập tin có chứa một trận đấu.

Nếu bạn muốn tìm tất cả các tệp trong hệ thống tệp kết thúc bằng .sh, bắt đầu từ thư mục gốc /, thì đó findlà công cụ thích hợp nhất.

Các khuyến nghị di động và hiệu quả nhất là:

find / -type f -name '*.sh' -exec grep -l word {} + 2>/dev/null

Điều này là dễ đọc như nó có được, và không khó để phân tích nếu bạn hiểu ngữ nghĩa đằng sau mỗi thành phần.

  • find /: chạy findbắt đầu từ gốc hệ thống tập tin,/
  • -type f: chỉ khớp với các tệp thông thường
  • -name '*.sh': ... và chỉ khớp các tệp có tên kết thúc bằng .sh
  • -exec ... {} +: lệnh chạy được chỉ định trong ...các tệp khớp trong nhóm, trong đó {}được thay thế bằng tên tệp trong nhóm. Ý tưởng là chạy lệnh trên càng nhiều tệp cùng một lúc càng tốt trong giới hạn của hệ thống ( ARG_MAX). Hiệu quả của {} +biểu mẫu đến từ việc giảm thiểu số lần ...lệnh phải được gọi bằng cách tối đa hóa số lượng tệp được truyền cho mỗi lần gọi ....
  • grep -l word {}: trong đó cái {}giống nhau được {}lặp lại từ phía trên và được thay thế bằng tên tệp. Như đã giải thích trước đó, grep -lin tên của các tệp chứa khớp word.
  • 2>/dev/null: ẩn thông báo lỗi (về mặt kỹ thuật, chuyển hướng lỗi tiêu chuẩn sang lỗ đen đó /dev/null). Điều này là vì lý do thẩm mỹ và thực tế, vì việc chạy findtrên /có thể sẽ dẫn đến các luồng tin nhắn "bị từ chối" mà bạn có thể không quan tâm đối với các tệp mà bạn không có quyền đọc và các thư mục bạn không có quyền truy cập.

Có một số vấn đề với các đề xuất bạn nhận được và đăng trong câu hỏi của bạn. Cả hai

grep word `find / -name \*.sh 2>/dev/null

find / -name "*.sh" 2>/dev/null | xargs grep word

thất bại trên các tập tin với khoảng trắng trong tên của họ. Tốt nhất là tránh đặt tên tập tin thay thế hoàn toàn. Cái đầu tiên có thêm vấn đề về khả năng chạy vào giới hạn ARG_MAX. Cái thứ hai gần với những gì tôi đề xuất, nhưng không có lý do chính đáng nào để sử dụng xargsở đây, chưa kể đến việc sử dụng an toàn và đúng cách xargsđòi hỏi phải hy sinh tính di động cho một số tùy chọn chỉ GNU ( find -print0 | xargs -0).


Cảm ơn bạn đã giải thích dễ hiểu và kỹ lưỡng!
paulrehkugler


2

Sự kết hợp của grepfindtrong nhiều trường hợp ack( betterthangrep.com ):

ack [OPTION]... PATTERN [FILE]

Ví dụ của bạn, hãy xem xét sử dụng

ack --shell word /

Ghi chú

ack

  • tìm kiếm (theo mặc định) đệ quy, nhưng
  • bỏ qua của (theo mặc định) thư mục từ hệ thống kiểm soát phiên bản phổ biến, ví dụ như .git, .hg, .svn, ...
  • có thể dễ dàng thu hẹp kết quả của bạn bằng cách sử dụng các bộ lọc cho các loại tệp phổ biến (xem bên dưới để biết các mẫu tên tệp riêng biệt)
  • grepcú pháp giống như và các đối số tương tự / tương tự như đối -ivới "trường hợp bỏ qua", v.v.
  • có thể được gọi ack-greptrên hệ thống của bạn (trên các bản phân phối dựa trên Debian, nếu tôi nhớ chính xác)

Mẫu tên tệp

Tùy chọn --shellnày là viết tắt --type=shellvà bao gồm một số loại tệp: hiện .sh .bash .csh .tcsh .ksh .zshtheo

ack --help-types

Nếu bạn chỉ muốn .shcác tệp, bạn phải xác định (thêm) loại của riêng mình shvà sử dụng bộ lọc này ( --sh) như thế này:

ack word --type-add=sh=.sh --sh /

Điều này nghe có vẻ hơi phức tạp, nhưng cho phép tìm kiếm đệ quy cho .shcác tệp bên dưới /. Đối với một tìm kiếm cục bộ (không chỉ định thư mục bắt đầu, ví dụ \) sẽ dễ dàng hơn:

ack word *.sh

Cảm ơn đã chỉ cho tôi ack, không bao giờ biết nó tồn tại, rất tiện dụng cho một dev!
huyền thoại2k
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.