Làm cách nào để tìm tất cả các tệp chứa văn bản cụ thể trên Linux?


5258

Tôi đang cố gắng tìm cách quét toàn bộ hệ thống Linux của mình cho tất cả các tệp có chứa một chuỗi văn bản cụ thể. Chỉ cần làm rõ, tôi đang tìm văn bản trong tệp chứ không phải trong tên tệp.

Khi tôi đang tìm cách làm điều này, tôi đã bắt gặp giải pháp này hai lần:

find / -type f -exec grep -H 'text-to-find-here' {} \;

Tuy nhiên, nó không hoạt động. Nó dường như hiển thị mọi tập tin duy nhất trong hệ thống.

Đây có phải là gần với cách thích hợp để làm điều đó? Nếu không, tôi nên làm thế nào? Khả năng tìm chuỗi văn bản này trong các tệp sẽ cực kỳ hữu ích cho một số dự án lập trình tôi đang thực hiện.


21
hãy nhớ rằng grep sẽ diễn giải bất kỳ .như một ký tự đại diện đơn, trong số những ký tự khác. Lời khuyên của tôi là luôn luôn sử dụng fgrep hoặc egrep.
Walter Tross

10
Dù sao, bạn đã gần như ở đó! Chỉ cần thay thế -Hbằng -l(và có thể grepbằng fgrep). Để loại trừ các tệp có các mẫu tên nhất định, bạn sẽ sử dụng findtheo cách nâng cao hơn. Thật đáng để học cách sử dụng find. Chỉ cần man find.
Walter Tross

6
find … -exec <cmd> +dễ gõ hơn và nhanh hơn find … -exec <cmd> \;. Nó chỉ hoạt động nếu <cmd>chấp nhận bất kỳ số lượng đối số tên tệp. Việc tiết kiệm thời gian thực hiện đặc biệt lớn nếu <cmd>bắt đầu chậm như các tập lệnh Python hoặc Ruby.
hagello

Để tìm kiếm không đệ quy trong một đường dẫn cụ thể, lệnh là `grep --include = *. Txt -snw" mẫu "thepath / *.
Stéphane Laurent

@ StéphaneLaurent Tôi nghĩ bạn đang làm phức tạp nó quá nhiều. Chỉ cần nóigrep "pattern" path/*.txt
fedorqui 'SO ngừng làm hại'

Câu trả lời:


9521

Làm như sau:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -rhoặc -Rlà đệ quy,
  • -n là số dòng và
  • -w là viết tắt của từ phù hợp với toàn bộ từ.
  • -l (chữ thường L) có thể được thêm vào để chỉ cung cấp tên tệp của tệp phù hợp.

Cùng với đó, --exclude, --include, --exclude-dircờ có thể được sử dụng để tìm kiếm hiệu quả:

  • Điều này sẽ chỉ tìm kiếm thông qua các tệp có phần mở rộng .c hoặc .h:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • Điều này sẽ loại trừ việc tìm kiếm tất cả các tệp kết thúc bằng phần mở rộng .o:

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • Đối với các thư mục, có thể loại trừ một thư mục cụ thể thông qua --exclude-dirtham số. Ví dụ: điều này sẽ loại trừ các dirs dir1 /, dir2 / và tất cả chúng đều khớp với * .dst /:

    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

Điều này làm việc rất tốt cho tôi, để đạt được mục đích gần như giống như của bạn.

Để biết thêm lựa chọn kiểm tra man grep.


74
sử dụng - bao gồm. như "grep -rnw --exclude = *. o 'thư mục' -e" mẫu "
rakib_

98
Điều đáng chú ý: có vẻ như rtùy chọn là lười biếng (đi qua độ sâu trước, hơn dừng sau thư mục đầu tiên), trong khi Rtham lam (sẽ đi ngang qua toàn bộ cây một cách chính xác).
Eliran Malka

5
grep -rnw "Chuỗi tôi đang tìm kiếm" đã thực hiện những gì tôi cần. Cảm ơn!
ViliusK

33
Lưu ý (đặc biệt đối với người mới): Dấu ngoặc kép trong lệnh trên rất quan trọng.
madD7

69
@Eliran Malka Ren rsẽ duyệt cả hai thư mục chính xác, nhưng Rsẽ theo các liên kết tượng trưng.
bzeaman

1499

Bạn có thể sử dụng grep -ilR:

grep -Ril "text-to-find-here" /
  • i là viết tắt của trường hợp bỏ qua (tùy chọn trong trường hợp của bạn).
  • R là viết tắt của đệ quy.
  • l là viết tắt của "hiển thị tên tệp, không phải kết quả chính nó".
  • / là viết tắt của bắt đầu từ gốc của máy tính của bạn.

85
Dựa trên kinh nghiệm của tôi, -inó làm cho nó chậm đi rất nhiều, vì vậy đừng sử dụng nó nếu không cần thiết. Kiểm tra nó trong một thư mục nhất định và sau đó khái quát hóa. Nó sẽ được hoàn thành trong vòng vài phút. Tôi nghĩ rằng một biểu thức thường xuyên sẽ làm cho nó chậm hơn. Nhưng ý kiến ​​của tôi dựa trên các giả định, tôi khuyên bạn nên kiểm tra nó timeở phía trước của dòng.
fedorqui 'SO ngừng làm hại'

4
Vâng, /*là viết tắt của điều đó. Dù sao tôi chỉ thử nó và nhận thấy rằng chỉ /hoạt động.
fedorqui 'SO ngừng làm hại'

10
Nếu bạn không tìm kiếm bằng regex, bạn có thể sử dụng fgrep thay cho grep trên hầu hết các hệ thống.
markle976

8
Có @ markle976, trên thực tế từ người đàn ông grep : fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed strings.
fedorqui 'SO ngừng làm hại'

17
Bạn có thể thay thế / với đường dẫn đến thư mục grep -Ril "text-to-find-here" ~/sites/hoặc sử dụng. cho thư mục hiện tạigrep -Ril "text-to-find-here" .
Đen

329

Bạn có thể sử dụng ack . Nó giống như grep cho mã nguồn. Bạn có thể quét toàn bộ hệ thống tập tin của bạn với nó.

Cứ làm đi:

ack 'text-to-find-here'

Trong thư mục gốc của bạn.

Bạn cũng có thể sử dụng các biểu thức thông thường , chỉ định kiểu tệp, v.v.


CẬP NHẬT

Tôi mới phát hiện ra The Silver Searcher , giống như ack nhưng nhanh hơn 3-5 lần so với nó và thậm chí bỏ qua các mẫu từ một .gitignoretệp.


57
Rất hữu ích, đơn giản và nhanh chóng. Cảnh báo: "Trên các bản phát hành có nguồn gốc từ Debian, ack được đóng gói là" ack-grep "vì" ack "đã tồn tại" (từ beyondgrep.com/install ). Cuối cùng, bạn có thể chạy trình chuyển đổi mã Kanji trên các
Linux

11
ack hoặc ack-grep có những điểm nổi bật đẹp, nhưng find + grep khi được sử dụng đúng cách sẽ hiệu quả hơn nhiều
Sławomir Lenart 11/215

14
Lưu ý rằng ripgrep nhanh hơn bất kỳ thứ gì khác được đề cập ở đây, bao gồm Trình tìm kiếm bạc và đơn giản 'ol grep. Xem bài đăng trên blog này để chứng minh.
Radon Rosborough

194

Bạn có thể dùng:

grep -r "string to be searched"  /path/to/dir

Các rchữ viết tắt của đệ quy và do đó sẽ tìm kiếm trong đường dẫn được chỉ định và các thư mục con của nó. Điều này sẽ cho bạn biết tên tệp cũng như in ra dòng trong tệp nơi chuỗi xuất hiện.

Hoặc một lệnh tương tự như lệnh bạn đang thử (ví dụ :) để tìm kiếm trong tất cả các tệp javascript (* .js):

find . -name '*.js' -exec grep -i 'string to search for' {} \; -print

Điều này sẽ in các dòng trong các tệp mà văn bản xuất hiện, nhưng nó không in tên tệp.

Ngoài lệnh này, chúng ta cũng có thể viết lệnh này: grep -rn "Chuỗi để tìm kiếm" / path / to / thư mục / hoặc / file -r: tìm kiếm đệ quy n: số dòng sẽ được hiển thị cho phù hợp


1
Thanx cho phiên bản tìm. Phiên bản grep của tôi (busybox cho NAS) không có tùy chọn -r, tôi thực sự cần một giải pháp khác!
jc

3
Cảm ơn bạn đã cho phiên bản 'tìm'! Điều quan trọng là có thể lọc theo ' .js' hoặc ' .txt', v.v. Không ai muốn dành hàng giờ để chờ grep hoàn thành việc tìm kiếm tất cả các video nhiều gigabyte từ kỳ nghỉ gia đình cuối cùng, ngay cả khi lệnh là dễ gõ hơn.
mightypile

grep tốt hơn phiên bản được chấp nhận, vì được chấp nhận không tìm kiếm một nửa từ
waza123

114

Bạn có thể sử dụng điều này:

grep -inr "Text" folder/to/be/searched/

12
dễ nhất, dài dòng, đệ quy và trường hợp không nhạy cảm. giơ ngón tay cái lên.
Francesco Casula

nếu bạn thêm -A3 thậm chí còn tốt hơn
albanx

73

Danh sách tên tệp chứa văn bản đã cho

Trước hết, tôi tin rằng bạn đã sử dụng -Hthay vì -l. Ngoài ra, bạn có thể thử thêm văn bản bên trong dấu ngoặc kép theo sau {} \.

find / -type f -exec grep -l "text-to-find-here" {} \; 

Thí dụ

Giả sử bạn đang tìm kiếm các tệp chứa văn bản cụ thể "Giấy phép Apache" trong thư mục của bạn. Nó sẽ hiển thị kết quả tương tự như bên dưới (đầu ra sẽ khác nhau dựa trên nội dung thư mục của bạn).

bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
./net/java/jvnet-parent/5/jvnet-parent-5.pom
./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
./commons-io/commons-io/2.4/commons-io-2.4.pom
bash-4.1$ 

Loại bỏ trường hợp nhạy cảm

Ngay cả khi bạn không sử dụng về trường hợp như "văn bản" so với "văn bản", bạn có thể sử dụng công -itắc để bỏ qua trường hợp. Bạn có thể đọc thêm chi tiết ở đây .

Hy vọng điều này sẽ giúp bạn.


2
Đó là những gì lệnh này thực hiện: findsẽ chuyển tất cả các đường dẫn mà nó tìm thấy cho lệnh grep -l "text-to-find-here" <file found>". Bạn có thể thêm các hạn chế cho tên tệp, ví dụ: find / -iname "*.txt"chỉ tìm kiếm trong các tệp có tên kết thúc bằng.txt
Mene

1
@Auxadder - bao gồm một đầu ra mẫu để tránh bất kỳ sự nhầm lẫn nào cho người đọc.
lkamal

2
.... Tôi muốn tin vào điều gì đó.
Pryftan

@Mene Điều đó được nói -inamelà không phân biệt chữ hoa chữ thường, có nghĩa là nó cũng sẽ tìm thấy các tệp .TXT, ví dụ, cũng như TxT và TXt, v.v.
Pryftan

66

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, như:

grep -r "class foo" .

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

Bạn cũng có thể sử dụng cú pháp toàn cầu để tìm kiếm trong các tệp cụ thể 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 "class foo" .

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 duy nhất có thể được khớp với nhiều mẫu chung.


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 cũng thấy mở rộng toàn cầu hữu ích. Nhưng hãy nhớ rằng nếu có số lượng tệp thực sự lớn, bạn có thể gặp lỗi "Danh sách đối số quá dài". (Globing đơn giản cũng dễ bị lỗi loại này).
Yoory N.

2
Đối với việc hít toàn bộ hệ thống tập tin, rg sẽ ít đau đớn hơn hầu hết các công cụ khác.
lk

55

Nếu bạn grepkhông hỗ trợ tìm kiếm đệ quy, bạn có thể kết hợp findvới xargs:

find / -type f | xargs grep 'text-to-find-here'

Tôi thấy điều này dễ nhớ hơn định dạng cho find -exec.

Điều này sẽ xuất tên tệp và nội dung của dòng phù hợp, ví dụ

/home/rob/file:text-to-find-here

Cờ tùy chọn bạn có thể muốn thêm vào grep:

  • -i - tìm kiếm không nhạy cảm
  • -l - chỉ xuất tên tệp nơi tìm thấy kết quả khớp
  • -h - chỉ xuất dòng phù hợp (không phải tên tệp)

3
Điều này tương đương với việc grep 'text-to-find-here'không có tên tệp nếu findkhông tìm thấy gì. Điều này sẽ treo và chờ người dùng nhập liệu! Thêm --no-run-if-emptydưới dạng tùy chọn xargs.
hagello

3
Sự kết hợp giữa find và xargs này không hoạt động như dự định nếu tên tệp hoặc thư mục chứa khoảng trắng (các ký tự xargs diễn giải là dấu phân cách). Sử dụng find … -exec grep … +. Nếu bạn khăng khăng sử dụng find cùng với xargs, hãy sử dụng -print0-0.
hagello

43
grep -insr "pattern" *
  • i: Bỏ qua các phân biệt trường hợp trong cả tệp THỰC HIỆN và các tệp đầu vào.
  • n: Tiền tố mỗi dòng đầu ra với số dòng dựa trên 1 trong tệp đầu vào của nó.
  • s: Loại bỏ các thông báo lỗi về các tệp không tồn tại hoặc không thể đọc được.
  • r: Đọc tất cả các tệp trong mỗi thư mục, đệ quy.

3
Bạn có thể giải thích làm thế nào câu trả lời của bạn cải thiện các câu trả lời khác, hoặc làm thế nào nó đủ khác với chúng?
Amos M. Carpenter

không phức tạp lắm để nhớ, sẽ bao gồm tất cả các mẫu (case-senstivity -> off, bao gồm tên tệp và số dòng và sẽ tìm kiếm đệ quy, v.v.) và cuối cùng sẽ sử dụng "*" để tìm kiếm tất cả các thư mục (không cần chỉ định đường dẫn hoặc tên thư mục).
enfinet

Xin lỗi, tôi nên nói rõ hơn: sẽ thật tuyệt nếu bạn có thể đưa lời giải thích đó vào câu trả lời của mình. Vì hiện tại, đặc biệt là với rất nhiều câu trả lời tương tự khác, thật khó để nhận ra từ một câu trả lời ngắn như vậy lợi ích của việc thử đối với câu trả lời được chấp nhận hoặc một trong những câu trả lời sẽ là gì.
Amos M. Carpenter

6
@ AmosM.Carpenter Một điều tôi thích về câu trả lời này là chỉ ra đối số triệt tiêu, có thể giúp lọc tiếng ồn không quan trọng để có được kết quả mà chúng ta thực sự muốn. Grep in các lỗi như, "Chức năng không được triển khai", "Đối số không hợp lệ", "Tài nguyên không khả dụng", v.v. trên một số "tệp" nhất định.
leetNightshade

@leetNightshade: Tôi cho rằng bạn đang gửi bình luận của bạn cho tôi vì tôi đã yêu cầu một lời giải thích về bài đăng gốc thưa thớt. Xin vui lòng xem bản sửa đổi tuyệt vời của Fabio cho ý kiến ​​trước đây của tôi để có ý nghĩa.
Amos M. Carpenter

39

Có một tiện ích mới gọi là The Silversearcher

sudo apt install silversearcher-ag

Nó hoạt động chặt chẽ với Git và các VCS khác. Vì vậy, bạn sẽ không nhận được bất cứ điều gì trong một thư mục .git hoặc thư mục khác.

Bạn chỉ có thể sử dụng

ag "Search query"

Và nó sẽ làm nhiệm vụ cho bạn!


35

Làm cách nào để tìm tất cả các tệp chứa văn bản cụ thể trên Linux? (...)

Tôi đã xem qua giải pháp này hai lần:

find / -type f -exec grep -H 'text-to-find-here' {} \;


Nếu sử dụng find like trong ví dụ của bạn, tốt hơn hãy thêm -s( --no-messages) vào grep2>/dev/nullở cuối lệnh để tránh nhiều tin nhắn bị từ chối cấp phép do grepfind:

find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

find là công cụ tiêu chuẩn để tìm kiếm tệp - kết hợp với grep khi tìm kiếm văn bản cụ thể - trên các nền tảng giống như Unix. Nhân tiện,lệnh find thường được kết hợp với xargs .

Các công cụ nhanh hơn và dễ dàng hơn tồn tại cho cùng một mục đích - xem bên dưới. Tốt hơn hãy thử chúng, miễn là chúng có sẵn trên nền tảng của bạn , tất nhiên:

Các lựa chọn thay thế nhanh hơn và dễ dàng hơn

RipGrep - công cụ tìm kiếm nhanh nhất xung quanh:

rg 'text-to-find-here' / -l

Người tìm kiếm bạc :

ag 'text-to-find-here' / -l

ack :

ack 'text-to-find-here' / -l

Lưu ý: Bạn cũng có thể thêm 2>/dev/nullvào các lệnh này để ẩn nhiều thông báo lỗi.


Cảnh báo : trừ khi bạn thực sự không thể tránh được, đừng tìm kiếm từ '/' (thư mục gốc) để tránh tìm kiếm dài và không hiệu quả! Vì vậy, trong các ví dụ ở trên, bạn nên thay thế ' / ' bằng tên thư mục con, ví dụ: "/ home" tùy thuộc vào nơi bạn thực sự muốn tìm kiếm ...


'find là công cụ tiêu chuẩn để tìm kiếm các tệp chứa văn bản cụ thể trên các nền tảng giống Unix' đối với tôi có vẻ khá mơ hồ. Ngay cả bên cạnh đệ quy grep findcũng không trực tiếp tìm kiếm bên trong tệp cho văn bản. Và có thể những công cụ bổ sung đó hữu ích với một số người nhưng những người yêu thích thời gian cũ và những người quen thuộc với ví dụ như grepsẽ không cung cấp cho họ bất cứ lúc nào (tôi chắc chắn sẽ không). Không nói rằng họ vô dụng mặc dù.
Pryftan

".... chứa văn bản cụ thể ...": phần này của câu không chính xác (vì nó không tìm thấy chính nó liên quan đến phần tìm kiếm này). Đã chỉnh sửa. Cảm ơn.
Bludzee

Vinh dự khi được giup bạn! Điều duy nhất khác trong nháy mắt rất rất nhanh chóng được thay đổi từ thư mục để thư mục nhưng tôi biết đó là một cuộc thập tự chinh của tôi, tôi sẽ không bao giờ giành chiến thắng hoàn toàn. Không từ bỏ mặc dù ...
Pryftan

Tại sao không phải là "thư mục" thay vì "thư mục", nhưng tại sao? Hãy chia sẻ "cuộc thập tự chinh" của bạn!
Bludzee

Tôi đang nói sử dụng thư mục thay thế! Đề cập đến: bạn nên thay thế '/' bằng một tên thư mục con Và đó là một tiểu thư thú cưng của tôi .. đặc biệt kể từ khi Windows sử dụng để gọi nó là 'thư mục'. À..có thể bạn đã hiểu điều đó. Tại sao? À bởi vì đó là những gì nó được gọi. Nó cũng được gọi là ở cấp hệ thống tập tin. Và nhìn vào nó theo cách này: nó đã từng được gọi (đối với DOS) folchưa? Tất nhiên là không rồi; nó đã được gọi dir(và tôi tin rằng nó vẫn còn). Thư mục là một thứ được dành cho (tôi đoán) sự thân thiện với người dùng mặc dù trong trường hợp này có thể làm giảm bớt nó cho người dùng ít 'tiên tiến'?
Pryftan

29

Thử:

find . -name "*.txt" | xargs grep -i "text_pattern"

5
Đây thực sự là một ví dụ điển hình khi KHÔNG sử dụng xargsnhư vậy .. hãy xem xét điều này. echo "file bar.txt has bar" > bar.txt; echo "file foo bar.txt has foo bar" > "foo bar.txt"; echo "You should never see this foo" > foo; find . -name "*.txt" | xargs grep -i foo # ./foo:You should never see this foo. Ở xargsđây khớp với tệp SAU và KHÔNG khớp với tệp dự định. Hoặc là sử dụng find .. -print0 | xargs -0 ...nhưng đó là việc sử dụng đường ống vô dụng hoặc tốt hơnfind ... -exec grep ... {} +
shalomb

29

Sử dụng pwdđể tìm kiếm từ bất kỳ thư mục bạn đang ở, đệ quy xuống

grep -rnw `pwd` -e "pattern"

Cập nhật Tùy thuộc vào phiên bản grep bạn đang sử dụng, bạn có thể bỏ qua pwd. Trên các phiên bản mới hơn .dường như là trường hợp mặc định cho grep nếu không có thư mục nào được đưa ra, do đó:

grep -rnw -e "pattern"

hoặc là

grep -rnw "pattern"

sẽ làm điều tương tự như trên!


3
sử dụng pwdlà không cần thiết ở tất cả, vì nó là mặc định. grep -rnw "pattern"đủ.
fedorqui 'SO ngừng làm hại'

và trên thực tế grep -rnwvà tương tự là những gì đã được trả lời như ba năm trước, tôi không thấy câu trả lời này làm tăng giá trị như thế nào.
fedorqui 'SO ngừng làm hại'

Câu trả lời được chọn không hiển thị mẫu mặc định và 5 người dường như đã thấy nó hữu ích
mahatmanich

Bạn có ý nghĩa gì với "mẫu mặc định"? Câu trả lời được chấp nhận chứa grep -rnw '/path/to/somewhere/' -e "pattern"những gì bạn có ở đây. 5 phiếu sau 2,3 ​​triệu lượt truy cập không có nghĩa là nhiều.
fedorqui 'SO ngừng làm hại'

Tôi đồng ý :-) điều tôi thiếu trong câu trả lời ban đầu là trường hợp sử dụng mà bạn hoàn toàn không phải đưa ra một đường dẫn hoặc tìm kiếm thư mục hiện tại một cách đệ quy không được phản ánh trong câu trả lời được chấp nhận. Do đó, đó là một kinh nghiệm học tập tốt về grep để đào sâu hơn một chút.
mahatmanich

19

grep có thể được sử dụng ngay cả khi chúng ta không tìm kiếm một chuỗi.

Đơn giản là chạy

grep -RIl "" .

sẽ in ra đường dẫn đến tất cả các tệp văn bản, tức là những tệp chỉ chứa các ký tự có thể in được.


2
Tôi không thấy cách này tốt hơn là sử dụng một cách đơn thuần lshoặc find(cho đệ quy)
fedorqui 'SO dừng làm hại'

17

Dưới đây là danh sách một số lệnh có thể được sử dụng để tìm kiếm tệp.

grep "text string to search” directory-path

grep [option] "text string to search” directory-path

grep -r "text string to search” directory-path

grep -r -H "text string to search” directory-path

egrep -R "word-1|word-2” directory-path

egrep -w -R "word-1|word-2” directory-path

5
Điều này thêm vào câu trả lời hiện có là gì?
fedorqui 'SO ngừng làm hại'

@fedorqui egreptương đương grep -Evà có nghĩa là --extended-regexpbạn có thể tìm thấy thông tin chi tiết tại đây unix.stackexchange.com/a/17951/196072
omerhakanbilici


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

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

find là 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 specifies that it should proceed only files, not directories etc.
-exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename

15

Thử:

find / -type f -exec grep -H 'text-to-find-here' {} \;

Nó sẽ tìm kiếm tất cả các hệ thống tập tin, bởi vì /là thư mục gốc.

Đối với thư mục nhà sử dụng:

find ~/ -type f -exec grep -H 'text-to-find-here' {} \;

Đối với thư mục hiện tại sử dụng:

find ./ -type f -exec grep -H 'text-to-find-here' {} \;

Có lẽ nhiều chi tiết về sự khác biệt của các thư mục là rõ ràng đối với nhiều người ... nhưng cũng rất hữu ích cho người mới. +1
nilon

1
Điều này thêm vào câu trả lời hiện có là gì?
fedorqui 'SO ngừng làm hại'

Gọi nó là cuộc thập tự chinh của tôi nhưng từ này là 'thư mục'. Đây không phải là Windows (trước đây thường sử dụng 'thư mục' - trước 9x). Làm ơn ngừng nói 'thư mục'. Đối với lệnh cuối cùng của bạn, bạn thậm chí không cần '/' chỉ FYI.
Pryftan

15

Hy vọng đây là sự giúp đỡ ...

Mở rộng grepmột chút để cung cấp thêm thông tin trong đầu ra, ví dụ, để lấy số dòng trong tệp nơi văn bản có thể được thực hiện như sau:

find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"

Và nếu bạn có ý tưởng loại tệp là gì, bạn có thể thu hẹp tìm kiếm của mình bằng cách chỉ định tiện ích mở rộng loại tệp để tìm kiếm, trong trường hợp này .pasHOẶC .dfmtệp:

find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"

Giải thích ngắn về các tùy chọn:

  1. .trong findchỉ định từ thư mục hiện tại.
  2. -name" *.*": Cho tất cả các file (-name " *.pas" -o -name " *.dfm"): Chỉ có *.pasHOẶC *.dfmfile, HOẶC định với-o
  3. -type f xác định rằng bạn đang tìm kiếm tập tin
  4. -print0--nullở phía bên kia của |(ống) là những người rất quan trọng, đi qua các tên tập tin từ findđến grepnhúng trong xargs, cho phép sự ra đi của tên tập tin với không gian trong tên tập tin, cho phép grep để điều trị đường dẫn và tên tập tin là một chuỗi, và không phá vỡ nó trên mỗi không gian.

-name '*.*'không phải những gì bạn nói; nó sẽ không chọn một tệp gọi là 'tệp' vì mẫu không tương đương với tệp đó (không có .ext); *tuy nhiên (tốt. tập tin sang một bên). Nhưng có một điều khác: nếu bạn muốn tất cả các tệp tại sao phải chỉ định tên tệp ở vị trí đầu tiên? Không có nhận xét nào khác - ngoại trừ việc thật tốt khi biết rằng vẫn có những người không sử dụng thuật ngữ 'thư mục' của MS (mà thực sự sau khi nói nó đủ tôi sẽ không thêm nhưng tôi muốn chỉ ra tuyên bố hơi sai mà bạn đã đưa ra với tên tệp - cũng như sự dư thừa / vô dụng trong trường hợp 'tất cả').
Pryftan

15

Một đơn giản findcó thể làm việc tiện dụng. bí danh nó trong ~/.bashrctập tin của bạn :

alias ffind find / -type f | xargs grep

Bắt đầu một thiết bị đầu cuối mới và vấn đề:

ffind 'text-to-find-here'

14

Tôi đã viết một kịch bản Python có chức năng tương tự. Đây là cách người ta nên sử dụng kịch bản này.

./sniff.py path pattern_to_search [file_pattern]

Đối số đầu tiên path, là thư mục mà chúng ta sẽ tìm kiếm đệ quy. Đối số thứ hai pattern_to_search, là một biểu thức chính quy mà chúng ta muốn tìm kiếm trong một tệp. Chúng tôi sử dụng định dạng biểu thức chính quy được xác định trong thư viện Python re . Trong kịch bản này, .cũng phù hợp với dòng mới.

Đối số thứ ba file_pattern, là tùy chọn. Đây là một biểu thức chính quy khác hoạt động trên tên tệp. Chỉ những tệp phù hợp với biểu thức chính quy này mới được xem xét.

Ví dụ: nếu tôi muốn tìm kiếm các tệp Python có phần mở rộng pychứa từ Pool(theo sau Adaptor, tôi sẽ làm như sau,

./sniff.py . "Pool(.*?Adaptor"  .*py
./Demos/snippets/cubeMeshSigNeur.py:146 
./Demos/snippets/testSigNeur.py:259 
./python/moose/multiscale/core/mumbl.py:206 
./Demos/snippets/multiComptSigNeur.py:268 

Và voila, nó tạo ra đường dẫn của các tệp và số dòng trùng khớp mà tại đó kết quả khớp được tìm thấy. Nếu tìm thấy nhiều kết quả trùng khớp, thì mỗi số dòng sẽ được thêm vào tên tệp.


14

Nếu bạn thực sự muốn sử dụng findthì hãy sử dụng find + grep:

find /path/to/somewhere/ -type f -exec grep -nw 'textPattern' {} \;

các bước:

1.Sử dụng findđể tìm kiếm tập tin,
2.Sau đó thực hiện greptrên tất cả chúng.

Điều này có thể cung cấp cho bạn sức mạnh của findviệc tìm kiếm các tập tin.

  • Sử dụng -name Patternnếu bạn chỉ muốn grepmột số tệp nhất định:

    find /path/to/somewhere/ -type f -name \*.cpp -exec grep -nw 'textPattern' {} \;

Bạn có thể chơi với nó và sử dụng các tùy chọn khác nhau findđể cải thiện hoặc thu hẹp tìm kiếm tệp của bạn.


Sự khác biệt là gì? Nó sẽ làm việc với khoảng trắng trong đường dẫn tập tin?
Peter Mortensen

13

Sử dụng:

grep -c Your_Pattern *

Điều này sẽ báo cáo có bao nhiêu bản sao của mẫu của bạn trong mỗi tệp trong thư mục hiện tại.


13

grep là người bạn tốt của bạn để đạt được điều này.

grep -r <text_fo_find> <directory>

Nếu bạn không quan tâm đến trường hợp văn bản cần tìm, thì hãy sử dụng:

grep -ir <text_to_find> <directory>

Trong trường hợp của tôi, có vẻ như nó tìm kiếm ở mọi nơi ngay cả khi tôi chỉ định thư mục
Pathros

@Pathros Có lẽ phải làm với đệ quy được kích hoạt và thư mục bạn chỉ định. Đặt một cách đệ quy khác làm thay đổi mọi thứ theo cách đó.
Pryftan

@Pathros Ồ và nếu có bất kỳ -s nào trong chuỗi tìm kiếm, bạn sẽ muốn chuyển --đến grep trước; Điều đó có thể gây ra tác dụng phụ thú vị khác!
Pryftan

13

Tôi bị mê hoặc bởi cách grep đơn giản làm cho nó với 'rl':

grep -rl 'pattern_to_find' /path/where/to/find

-r to recursively find a file / directory inside directories..
-l to list files matching the 'pattern'

Sử dụng '-r' không có 'l' để xem tên tệp theo sau là văn bản tìm thấy mẫu !

grep -r 'pattern_to_find' /path/where/to/find

Nó hoạt động hoàn hảo ...


Điều này cũng hoạt động trong Git Bash (Windows).
Peter Mortensen

Nhưng nó ngụ ý mọi tệp phải được tìm kiếm (không có bộ lọc về tên tệp hoặc cấp độ mở rộng tệp, như .txt). Hoặc có một cách để làm điều đó?
Peter Mortensen

12

Để 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;

1
Tôi chỉ thấy nhược điểm so với việc sử dụng find … -exec grep 'str' {} \;(nếu bạn phải sử dụng findtất cả).
phk

1
Điều này sẽ phá vỡ khủng khiếp nếu bất kỳ tệp nào được tìm thấy findtrong khoảng trắng .. bạn có thể kết thúc greppingcác tệp sai và / hoặc thiếu các tệp đúng hoàn toàn. Chỉ cần sử dụng find ... -exec grep ...nếu bạn có nhu cầu sử dụng find.. nhưng trong trường hợp này là grep -r ...đủ.
shalomb

1
điểm của việc sử dụng một vòng lặp trên các kết quả tìm thấy sau đó grep là gì? Điều này trở nên phức tạp không cần thiết.
fedorqui 'SO ngừng làm hại'

12

Có một ackcông cụ sẽ làm chính xác những gì bạn đang tìm kiếm.

http://linux.die.net/man/1/ack

ack -i search_string folder_path/*

Bạn có thể bỏ qua -icho tìm kiếm trường hợp nhạy cảm


2
Điều này thêm vào câu trả lời hiện có là gì? Điều này đã được đề xuất hơn ba năm trước.
fedorqui 'SO ngừng làm hại'

1
@fedorqui 1) không có đường ống! 2) Sử dụng biểu thức thông thường 3) Nhận số dòng, tên tệp có đường dẫn tương đối, văn bản được tô sáng, v.v ... hữu ích để chỉnh sửa sau khi tìm kiếm, ví dụ: "vim + lineno path / file.cpp" sẽ giúp bạn hiểu đúng về dòng không quan tâm. Xem đầu ra của lệnh "ack bao gồm \ | hpp" tìm kiếm từ khóa "bao gồm" hoặc "hpp" trong thư mục tìm kiếm và thư mục con của tôi. Tôi hy vọng quan điểm là rõ ràng. Dưới đây là đầu ra mẫu (Không thể hiển thị các điểm nổi bật của từ khóa bằng văn bản đơn giản) process / child.hpp 11: boost / process / child.hpp process / all.hpp 21: #include <boost / process / exec.hpp>
Pal

12

Tất cả các câu trả lời trước đề nghị grep và tìm. Nhưng có một cách khác: Sử dụng Midnight Commander

Nó là một tiện ích miễn phí (30 tuổi, được chứng minh theo thời gian) trực quan mà không phải là GUI. Nó có vô số chức năng và việc tìm kiếm các tập tin chỉ là một trong số đó.


kiểm lâm sẽ có cùng ý tưởng
nilon

11

Lệnh dưới đây sẽ hoạt động tốt cho phương pháp này:

find ./ -name "file_pattern_name"  -exec grep -r "pattern" {} \;

2
điểm sử dụng findvà sau đó là grep -rgì? Chúng có nghĩa là như nhau, vì vậy điều này là dư thừa.
fedorqui 'SO ngừng làm hại'

ồ !! Đã sửa, Thực sự tìm thấy là để chạy grep trên các tệp được lọc và không phải tất cả, cảm ơn
Pradeep Goswami

2
Tuy nhiên, điều này không có ý nghĩa gì, bạn có thể lọc với find.
fedorqui 'SO ngừng làm hại'

11

Tránh những rắc rối và cài đặt ack-grep. Nó loại bỏ rất nhiều vấn đề cho phép và báo giá.

apt-get install ack-grep

Sau đó vào thư mục bạn muốn tìm kiếm và chạy lệnh bên dưới

cd /
ack-grep "find my keyword"
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.