Làm cách nào để sử dụng lệnh của grep Viking để tìm văn bản bao gồm các thư mục con


373

Tôi muốn tìm tất cả các tệp có chứa một chuỗi văn bản cụ thể. Các greplệnh làm việc, nhưng tôi không biết làm thế nào để sử dụng nó cho tất cả các thư mục (tôi chỉ có thể làm điều đó cho thư mục hiện tại của tôi). Tôi đã thử đọc man grep, nhưng nó không mang lại bất kỳ sự giúp đỡ nào.


grep -RIn <yor mẫu> * Sẽ tìm kiếm từ các thư mục hiện tại trong tất cả các tệp văn bản. Không chắc chắn làm thế nào để thực hiện tìm kiếm của tôi theo cách đệ quy trong các mẫu tệp như * .C chỉ với grep

1
Ký tự đại diện với --include="*.C"tùy chọn, @ user311346, nhờ @Lekensteyn.
Bob Stein

Sử dụng kết hợp find và grep để tìm kiếm đệ quy các tệp trong một chuỗi trong các thư mục hiện tại và tất cả các thư mục con. Kiểm tra wildderator.com/find-files-contained-my-text
Drona

Câu trả lời:


487

Nó sẽ tốt hơn để sử dụng

grep -rl "string" /path

Ở đâu

  • -r(hoặc --recursive) tùy chọn được sử dụng để duyệt qua tất cả các thư mục con của /path, trong khi
  • -l--files-with-matchesTùy chọn (hoặc ) được sử dụng để chỉ in tên tệp của các tệp phù hợp và không in các dòng khớp (điều này cũng có thể cải thiện tốc độ, với điều kiện grepdừng đọc tệp ở lần khớp đầu tiên với tùy chọn này).

13
Trên thực tế nếu "chuỗi" là một mẫu văn bản cần tìm, thì tốt hơn là sử dụng chức năng đó, nếu không thì ai đó có thể gặp vấn đề khi chuỗi chứa dấu chấm hoặc ký tự đặc biệt có ý nghĩa trong biểu thức thông thường và không chỉ là dấu chấm nên được tìm thấy dưới dạng chuỗi , như là Sau đó, tôi sẽ sử dụng các -rlFcông tắc, -Fcho "chuỗi cố định" (chứ không phải regrec - chẳng hạn). Tất nhiên, nếu tác vụ đang sử dụng regexps, thì xin lỗi. Chắc chắn, cùng một lý thuyết mà không có -r, tôi thường thấy rằng mọi người giả định grep tìm kiếm "văn bản" và nó có thể gây ra vấn đề trong đó những cái đặc biệt có nghĩa là một thứ regrec.
LGB

4
Ngoài ra còn có -icờ mà bỏ qua trường hợp.
Marco Ceppi

3
Tôi sẽ chỉ hiển thị --recursivetùy chọn, có rất nhiều tùy chọn và kịch bản sử dụng mà người ta có thể nói đến. Tôi bắt đầu từ câu trả lời chấp nhận @dmityugov và sửa đổi để làm việc mà không có find.
enzotib

1
@NN: xong :-)
enzotib

3
@ScottBiggs: với tùy chọn--include '*.h'
enzotib

167

Nếu bạn đang tìm kiếm các dòng khớp trong tệp, lệnh yêu thích của tôi là:

grep -Hrn 'search term' path/to/files
  • -H khiến tên tệp được in (ngụ ý khi nhiều tệp được tìm kiếm)
  • -r thực hiện tìm kiếm đệ quy
  • -n làm cho số dòng được in

path/to/filescó thể .tìm kiếm trong thư mục hiện tại

Các tùy chọn khác mà tôi thấy rất hữu ích:

  • -Ibỏ qua các tệp nhị phân (bổ sung: -acoi tất cả các tệp dưới dạng văn bản)
  • -Fcoi search termnhư một nghĩa đen, không phải là một biểu thức thông thường
  • -i thực hiện tìm kiếm không phân biệt chữ hoa chữ thường
  • --color=alwaysđể buộc màu ngay cả khi đường ống đi qua less. Để tạo lessmàu hỗ trợ, bạn cần sử dụng -rtùy chọn:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dirhữu ích để loại trừ các thư mục như .svn.git.

Ví dụ đầu ra


13
-Htrên một thư mục là dư thừa, nếu có nhiều hơn một tệp, như có thể xảy ra. Trên thực tế, trang người đàn ông nói-H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search.
enzotib

Tôi không biết rằng, nó luôn hoạt động như tôi mong đợi. Đó là lệnh mặc định của tôi khi tìm kiếm tệp.
Lekensteyn

1
Có cách nào để chỉ xem xét các tệp có phần mở rộng a, giả sử .a (và kết hợp điều này với -r) không?
dùng2413

6
@ user2413 Hãy thử--include '*.*'
Lekensteyn

1
@alper Hãy thửgrep --exclude='*~' ...
Lekensteyn

24

Tôi tin rằng bạn có thể sử dụng một cái gì đó như thế này:

find /path -type f -exec grep -l "string" {} \;

Giải thích từ ý kiến

findlà một lệnh cho phép bạn tìm các tệp và các đối tượng khác như thư mục và liên kết trong các thư mục con của một đường dẫn cụ thể. Nếu bạn không chỉ định một mặt nạ mà tên tệp sẽ đáp ứng, nó liệt kê tất cả các đối tượng thư mục.

  • -type f xác định rằng nó chỉ nên xử lý các tập tin, không phải thư mục, vv
  • -exec grepxác định rằng với mỗi tệp tìm thấy, nó sẽ chạy lệnh grep, truyền tên tệp của nó làm đối số cho nó, bằng cách thay thế {}bằng tên tệp

3
Chỉ dành cho những người không biết, việc thêm -name '*.py'giới hạn các trận đấu vào các tệp kết thúc bằng '.py'.
Daniel F

Tôi thích điều này bao gồm các khách hàng chưa thực hiện -R trong lệnh grep của họ.
Aviose

Nếu bạn muốn dòng phù hợp VÀ tên tệp được in, hãy thực hiện như sau:... -exec bash -c 'grep -r "mystring" {} && echo {}' \;
Donn Lee

những gì hoàn hảo tương đối để chỉ sử dụng grep trực tiếp?
jonathan

19

Lệnh mặc định của tôi là

grep -Rin string *

Tôi sử dụng thủ đô 'R' vì lssử dụng nó cho đệ quy. Vì grep chấp nhận cả hai, không có lý do gì để không sử dụng nó.

EDIT: mỗi HVNSweeting, rõ ràng -Rsẽ theo các liên kết tượng trưng nếu -rkhông.


1
Để tìm kiếm trong các tập tin ẩn quá, chạy shopt -s dotglob(nhớ -slà "thiết lập"). Hãy cẩn thận khi gỡ bỏ các tập tin sau đó. Nếu bạn đã bật dotglob, hãy rm -r *xóa mọi thứ trong thư mục hiện tại, nhưng cả thư mục phía trên nó vì nó ..khớp. Để tắt dotglob, sử dụng shopt -u dotglob("unset"). Những thay đổi là tạm thời, nó chỉ áp dụng cho shell hiện tại.
Lekensteyn

Tôi quên mất điều này. Có cách nào để đặt nó cho một dòng không? một cái gì đó như shopt -s dotglob & <grep cmd> & shopt -y dotglobchỉ thuận tiện hơn? Bằng cách này, chúng tôi sẽ không phải lo lắng về việc đặt lại nó
user606723

Ngoài ra, nó có thể dễ sử dụng hơn grep -Rin string .trong hầu hết các trường hợp này. Tôi chỉ sử dụng * bởi vì nó dường như đến một cách tự nhiên hơn.
dùng606723

1
nếu bạn thực hiện grep đệ quy, thì bạn chỉ có thể bắt đầu từ "." thay vì "*". không cần dotglob.
Michał rajer

1
bỏ phiếu này, một điều không được đề cập trong manpage là Rsẽ theo các liên kết tượng trưng, rkhông
HVNSweeting

12

Nếu bạn sẵn sàng thử một cái gì đó mới, hãy thử ack. Lệnh tìm kiếm đệ quy thư mục hiện tại stringlà:

ack string

Cài đặt khá đơn giản:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(Miễn là bạn đã có thư mục ~/binvà tốt nhất là trong thư mục của bạn PATH.)


2
Hoặc chỉ cần cài đặt apt-get ack-grep (và thêm bí danh ack = ack-grep vào .bashrc của bạn)
markijbema

Các tham số cuối cùng để chmodlệnh làm gì? Chúng cụ thể cho chmodhoặc chúng có liên quan đến bash ( !#:3phần)?
Elliott Darfink

@ElliottDarfink Đó là sử dụng tính năng lịch sử của Bash - !là một nhà chỉ định sự kiện . Chúng khá mạnh mẽ để tránh sự lặp lại. !#:3tham chiếu mã thông báo thứ ba của dòng lệnh cho đến nay, tức là ~/bin/acktrong trường hợp này.
Konrad Rudolph

4

Lệnh rgrep được dành riêng cho nhu cầu đó

Nếu không có sẵn, bạn có thể có được nó như thế này

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

Bạn có thể trực tiếp đặt vào các tùy chọn grep mặc định của mình như được mô tả ở trên.

Tôi sử dụng cá nhân

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

chủ đề liên quan: làm thế nào để luôn luôn sử dụng rgrep với màu sắc


rgrep được cung cấp bởi gói grep được cài đặt mặc định trong Ubuntu.
karel

2

Cập nhật 2:

Dòng lệnh này sử dụng findgrepkhắc phục sự cố:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> cho đầu ra màu:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

Thí dụ:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

Một ví dụ chạy trong ảnh chụp bên dưới: snap1


Cập nhật 1:

Bạn có thể thử mã sau đây; như một chức năng trong .bashrchoặc .bash_aliaseshoặc trong một tập lệnh:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

Sử dụng: wherein /path/to/search/in/ searchkeyword

thí dụ:

$ wherein ~/Documents/ "hello world"

(Lưu ý: Như được đề xuất trong các nhận xét bên dưới của @enzotib, điều này không hoạt động với tệp / thư mục bao gồm khoảng trắng trong tên của chúng.)


Bài gốc

Để tìm kiếm chuỗi và xuất ra chỉ dòng đó với chuỗi tìm kiếm:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

ví dụ:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

Để hiển thị tên tệp chứa chuỗi tìm kiếm:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

ví dụ:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

Thất bại trên tên tập tin chứa không gian. Sự thất bại được che giấu bởi thực tế là stderr không được hiển thị.
enzotib

@enzotib cảm ơn vì đã chỉ ra rằng .. điều đó vẫn chưa được giải quyết cho chức năng được chỉ định .. Tôi đã thêm một lớp lót khác ..
chính xác là

Bây giờ câu trả lời tương tự như của @dmityugov.
enzotib

đúng, nhưng theo nghĩa đó, hầu hết các câu trả lời trong trang này nếu bạn kiểm tra đều giống nhau về cách sử dụng grep, bên cạnh đó là tập hợp con sử dụng findvới grep... nhưng nếu bạn chấp nhận các công tắc và điều chỉnh khác nhau như một câu trả lời riêng biệt, có lẽ của tôi sẽ phù hợp ở đây quá .. hoặc bạn khác nhau? bản cập nhật cuối cùng thực hiện những gì tôi muốn trong tìm kiếm của mình: tên tệp có dòng với khóa tìm kiếm và dòng không. quá :) và bộ lọc lỗi và đầu ra màu để dễ đọc hơn ..
chính xác là

2

grep( GNU hoặc BSD )

Bạn có thể sử dụng grepcông cụ để tìm kiếm đệ quy thư mục hiện tại với -rtham số, như:

grep -r "pattern" .

Lưu ý: -r- Tìm kiếm đệ quy các thư mục con.

Để tìm kiếm trong các tệp cụ thể, bạn có thể sử dụng cú pháp toàn cầu hóa như:

grep "class foo" **/*.c

Lưu ý: Bằng cách sử dụng tùy chọn globalbing ( **), nó sẽ quét tất cả các tệp theo cách đệ quy với phần mở rộng hoặc mẫu cụ thể. Để kích hoạt cú pháp này, hãy chạy : shopt -s globstar. Bạn cũng có thể sử dụng **/*.*cho tất cả các tệp (không bao gồm ẩn và không có phần mở rộng) hoặc bất kỳ mẫu nào khác.

Nếu bạn có lỗi rằng đối số của bạn quá dài, hãy xem xét thu hẹp tìm kiếm của bạn hoặc sử dụng findcú pháp thay vì:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

Hoặc sử dụng ripgrep.

ripgrep

Nếu bạn đang làm việc trên các dự án lớn hơn hoặc các tệp lớn, bạn nên sử dụng ripgrepthay thế, như:

rg "pattern" .

Kiểm tra tài liệu, các bước cài đặt hoặc mã nguồn trên trang dự án GitHub .

Đó là nhanh hơn nhiều so với bất kỳ công cụ khác như GNU / BSD grep , ucg, ag, sift, ack, pthoặc tương tự, kể từ khi nó được xây dựng trên đầu trang của engine regex Rust trong đó sử dụng automata hữu hạn, SIMD và tối ưu hóa đen tích cực để giúp tìm kiếm rất nhanh.

Nó hỗ trợ bỏ qua các mẫu được chỉ định trong .gitignorecác tệp, do đó, một đường dẫn tệp có thể được khớp với nhiều mẫu toàn cục cùng một lúc.


Bạn có thể sử dụng các tham số phổ biến như:

  • -i - Tìm kiếm không nhạy cảm.
  • -I - Bỏ qua các tệp nhị phân.
  • -w - Tìm kiếm toàn bộ từ (ngược lại với từ ghép một phần).
  • -n - Hiển thị dòng của trận đấu của bạn.
  • -C/ --context(vd -C5) - Tăng ngữ cảnh, vì vậy bạn thấy mã xung quanh.
  • --color=auto - Đánh dấu văn bản phù hợp.
  • -H - Hiển thị tên tệp nơi tìm thấy văn bản.
  • -c- Hiển thị số lượng các dòng phù hợp. Có thể kết hợp với -H.

1

Tôi làm điều này bằng cách sử dụng xargs, một lệnh rất được đánh giá thấp

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

find ./ cung cấp cho bạn một danh sách đệ quy của tất cả các tệp trong một thư mục hiện tại, sau đó bạn chuyển nó thành xargs thực thi lệnh grep trên mỗi một trong các tệp đó


4
Sử dụng xargsmà không có -print0tùy chọn find-0tùy chọn xargsbị phản đối, nó sẽ thất bại đối với tên tệp có chứa khoảng trắng.
enzotib

@enzotib Tôi đã chỉnh sửa câu trả lời như bạn đề xuất.- vui lòng xem lại và nếu cần chỉnh sửa và sửa lỗi, tôi sẽ vui lòng chỉnh sửa lại bởi bạn. cảm ơn bạn
αғsнιη

1
@KasiyA: bây giờ đã ổn rồi, gỡ bỏ downvote của tôi.
enzotib

0

Tôi biết có rất nhiều câu trả lời ở đây, nhưng đây là một lựa chọn thay thế nếu bạn muốn thêm các hạn chế khác khi tìm kiếm các tệp:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

Điều này hoạt động vì grepsẽ trả về 0 nếu tìm thấy kết quả, 1 nếu không. Ví dụ: bạn có thể tìm thấy các tệp lớn 1 MB chứa nội dung nào đó:

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

Đối với nhiều yêu cầu, bạn có thể muốn sử dụng cờ tối ưu hóa -Otồn tại trong GNU grep.


0

Một tập lệnh (find-in-code) để tìm kiếm trong mã C, CPP:

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

Sử dụng:

find-in-code "search string"
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.