Làm thế nào để bỏ qua tên tập tin nhất định bằng cách sử dụng Tìm kiếm Tìm?


143

Một trong những lệnh BASH yêu thích của tôi là:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

tìm kiếm nội dung của tất cả các tệp tại và bên dưới thư mục hiện tại cho SearchString được chỉ định. Là một nhà phát triển, điều này đôi khi có ích.

Tuy nhiên, do dự án hiện tại của tôi và cấu trúc của cơ sở mã của tôi, tôi muốn làm cho lệnh BASH này nâng cao hơn nữa bằng cách không tìm kiếm bất kỳ tệp nào trong hoặc bên dưới thư mục chứa ".svn" hoặc bất kỳ tệp nào có chứa ".svn" hoặc bất kỳ tệp nào có kết thúc bằng ".html"

Các trang MAN để tìm loại làm tôi bối rối mặc dù. Tôi đã thử sử dụng -prune và nó cho tôi hành vi kỳ lạ. Trong một nỗ lực để chỉ bỏ qua các trang .html (để bắt đầu), tôi đã thử:

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

và không có được hành vi mà tôi đã hy vọng. Tôi nghĩ rằng tôi có thể đang thiếu quan điểm của -prune. Các bạn có thể giúp tôi không?

Cảm ơn


1
Chỉ cần fyi: findkhông phải là lệnh bash tích hợp mà là một chương trình riêng biệt
WakiMiko

1
Bạn có thể tìm kiếm bên trong tập tin vớigrep -rl 'SearchString'
emanuele

@emanuele Xin chào, chào mừng bạn đến với SuperUser (và mạng Stack Exchange). Đây là một câu hỏi tôi đã hỏi, và đã được trả lời, 2 năm rưỡi trước. Thông thường, nếu bạn muốn thêm câu trả lời cho câu hỏi, vui lòng làm như vậy bằng cách cuộn xuống phía dưới và trả lời ở đó, thay vì trong một bình luận. Vì câu hỏi này đã có câu trả lời được chấp nhận (câu hỏi có dấu kiểm màu xanh lá cây), tuy nhiên, không chắc là câu trả lời của bạn sẽ được chú ý nhiều, tuy nhiên. FYI.
Cody S

1
Xin chào, nó không phải là một câu trả lời cho câu hỏi của bạn. Đây chỉ là một mẹo, như bạn đã nói trong phần mở đầu sử dụng findđể tìm kiếm bên trong một tệp.
emanuele

2
FWIW, -name '*.*'không tìm thấy tất cả các tệp: chỉ những tệp có .tên của họ (việc sử dụng *.*thường là một DOS-ism, trong khi trong Unix, bạn thường chỉ sử dụng *cho điều đó). Để thực sự khớp tất cả, chỉ cần xóa hoàn toàn đối số : find . -exec .... Hoặc nếu bạn muốn chỉ áp dụng grep cho các tệp (và bỏ qua các thư mục) thì hãy làm find . -type f -exec ....
Stefan

Câu trả lời:


197

Bạn có thể sử dụng tính năng phủ định (!) Để tìm các tệp không khớp với các tên cụ thể:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Vì vậy, nếu tên kết thúc bằng .html hoặc chứa .svn ở bất kỳ đâu trong đường dẫn, nó sẽ không khớp và do đó, exec sẽ không được thực thi.


1
Tôi vẫn nên chỉ định -name ' . 'Ở đâu đó trong đó? Tôi sẽ làm điều đó trước, hoặc sau khi phủ định?
Cody S

Có phải ý định của *.*trận đấu của bạn để đảm bảo nó chỉ khớp với các tệp có chứa một .? Tìm sẽ khớp với tất cả các tệp trong trường hợp không có lệnh name, vì vậy phần trên sẽ khớp với mọi thứ trừ html và svn
Paul

5
Tôi nghĩ rằng bạn muốn -wholename '*.svn*'hơn là -name.
fuenfundachtzig

2
Có, nó có, để các .svnthư mục được loại trừ khỏi kết quả tìm kiếm.
fuenfundachtzig

1
@Noumenon ! -name '.'nên loại trừ .khỏi kết quả tìm kiếm.
Paul

11

Tôi đã có cùng một vấn đề trong một thời gian dài và có một số giải pháp có thể áp dụng trong các tình huống khác nhau:

  • ack-greplà một loại "nhà phát triển grep" mà theo mặc định bỏ qua các thư mục kiểm soát phiên bản và các tệp tạm thời. Các mantrang giải thích làm thế nào để tìm kiếm chỉ các loại tập tin cụ thể và làm thế nào để xác định của riêng bạn .
  • grep's riêng --exclude--exclude-dirtùy chọn có thể được sử dụng rất dễ dàng để bỏ qua tập tin globsđơn thư mục (không globbing cho các thư mục, không may).
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... nên hoạt động, nhưng các tùy chọn trên có lẽ ít gặp rắc rối trong thời gian dài.

9

Sau đây findlệnh nào thư mục mận có tên chứa .svn , Mặc dù nó không rơi vào các thư mục, tên đường dẫn tỉa được in ... ( -name '*.svn'là nguyên nhân!) ..

Bạn có thể lọc tên thư mục thông qua: grep -d skipâm thầm bỏ qua "tên thư mục" đầu vào như vậy.

Với GNU grep, bạn có thể sử dụng -Hthay vì /dev/null. Như một vấn đề phụ nhỏ: \+có thể nhanh hơn nhiều \;, ví dụ. cho 1 triệu file một dòng, sử dụng \;phải mất 4m20s , sử dụng \+nó chỉ mất 1.2s .

Phương pháp sau đây sử dụng xargsthay vì -execvà giả sử không có dòng mới \ntrong bất kỳ tên tệp nào của bạn . Như được sử dụng ở đây, xargsrất giống với find \+.

xargscó thể chuyển tên tệp chứa khoảng trắng liên tiếp bằng cách thay đổi dấu phân cách đầu vào '\n'thành -dtùy chọn.

Điều này loại trừ các thư mục có tên chứa .svn và chỉ các tệp không kết thúc bằng .html.

find . \( -name '*.svn*' -prune  -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'

1
Cảm ơn bạn đã chỉ ra các \+biến thể của hành động -exec. Hoan hô cho các vấn đề phụ nhẹ!
Christian Long

Tất nhiên, vì +không phải là một ký tự đặc biệt cho trình bao, bạn không cần phải nhập \trước nó.
Scott
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.