a

Câu hỏi Làm cách nào để tìm tất cả các tệp có chứa văn bản cụ thể trên Linux?


Tôi đang cố gắng tìm một cách để quét toàn bộ hệ thống Linux của tôi 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, 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 đã xem xét 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. Có vẻ như để hiển thị mọi tập tin trong hệ thống.

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


3693
2018-06-06 08:06


gốc


hãy nhớ rằng grep sẽ giải thích bất kỳ . như một ký tự đại diện một ký tự, trong số những ký tự khác. Lời khuyên của tôi là luôn luôn sử dụng hoặc fgrep hoặc egrep. - Walter Tross
dù sao, bạn đã gần như ở đó! Chỉ cần thay thế -H với -l (và có thể grep với 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, Tuy nhiên. Chỉ man find. - Walter Tross
find … -exec <cmd> + dễ dàng nhập và nhanh hơn find … -exec <cmd> \;. Nó chỉ hoạt động nếu <cmd> chấp nhận bất kỳ số đối số tên tệp nào. 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 kịch bản lệnh Python hoặc Ruby. - hagello
Để tìm kiếm không đệ quy trong một đường dẫn cụ thể, lệnh này là `grep --include = *. Txt -snw" mẫu "thepath / *. - Stéphane Laurent
@ StéphaneLaurent Tôi nghĩ rằng bạn đang làm phức tạp quá nhiều. Chỉ nói grep "pattern" path/*.txt - fedorqui


Các câu trả lời:


Làm như sau:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -r hoặc là -R là đệ quy,
  • -n là số dòng và
  • -w phù hợp với toàn bộ từ.
  • -l (thấp hơn trường hợp L) có thể được thêm vào chỉ cần cung cấp cho tên tập tin của các tập tin phù hợp.

Cùng với những thứ này, --exclude, --include, --exclude-dir cờ 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ó đuôi .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-dir tham số. Ví dụ, điều này sẽ loại trừ dirs dir1 /, dir2 / và tất cả chúng 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 gần như cùng một mục đích như của bạn.

Để có thêm tùy chọn kiểm tra man grep.


6681
2018-06-06 08:21



sử dụng --loại trừ. như "grep -rnw --exclude = *. o 'directory' -e" pattern " - rakib_
Tôi tìm thấy tham số của grep --include rất hữu ích. Ví dụ: grep -rnw --include = *. Java. -E "bất cứ điều gì tôi đang tìm kiếm" - Lucas A.
nó đáng chú ý: có vẻ như r tùy chọn là lười (vượt qua độ sâu đầu tiên, hơn điểm dừng sau thư mục đầu tiên), trong khi R là tham lam (sẽ đi qua toàn bộ cây một cách chính xác). - Eliran Malka
Lưu ý (đặc biệt là đối với người mới): Dấu ngoặc kép trong lệnh trên là quan trọng. - madD7
@Eliran Malka R vi r cả hai sẽ duyệt qua các thư mục một cách chính xác, nhưng R sẽ theo các liên kết tượng trưng. - bzeaman


Bạn có thể 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 viết tắt của đệ quy.
  • l viết tắt của "hiển thị tên tệp, không phải là kết quả".
  • / là viết tắt của bắt đầu từ gốc của máy tính của bạn.

1087
2018-06-06 08:08



Dựa trên kinh nghiệm của tôi, -i làm cho nó chậm lại rất nhiều, do đó, khô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 đó tổng quát. 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 chính quy sẽ làm cho nó chậm hơn. Nhưng nhận xét của tôi dựa trên giả thuyết, tôi đề nghị bạn thử nghiệm nó với time ở phía trước của dòng. - fedorqui
Vâng, /* là viết tắt của điều đó. Dù sao tôi chỉ thử nghiệm nó và nhận thấy rằng / công trinh. - fedorqui
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
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
Bạn có thể thay thế / bằng đường dẫn đến thư mục grep -Ril "text-to-find-here" ~/sites/ hoặc dùng . cho thư mục hiện tại grep -Ril "text-to-find-here" . - Black


Bạn có thể 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ể dùng cụm từ thông dụng, chỉ định loại tệp, v.v.


CẬP NHẬT

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


234
2018-06-06 08:26



Rất hữu ích, đơn giản và nhanh chóng. Cảnh báo: "Trên distro có nguồn gốc Debian, ack được đóng gói là" ack-grep "vì" ack "đã tồn tại" (từ beyondgrep.com/install). Bạn có thể sẽ chạy trình chuyển đổi mã Kanji trên các Linux đó ... - Jose_GD
ack hoặc ack-grep có điểm nổi bật tốt đẹp, nhưng tìm thấy + grep khi sử dụng thích hợp là tốt hơn nhiều trong hiệu suất - Sławomir Lenart
Lưu ý rằng ripgrep nhanh hơn bất cứ điều gì khác được đề cập ở đây, bao gồm cả Silver Searcher và plain 'ol grep. Xem bài đăng trên blog này để chứng minh. - Radon Rosborough


Bạn có thể dùng:

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

Các r là viết tắt của đệ quy và do đó sẽ tìm kiếm trong đường dẫn được chỉ định và cũng có 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 cố gắng (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 tin mà văn bản xuất hiện, nhưng nó không in tên tập tin.

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


126
2018-03-14 23:29



Thanx cho phiên bản tìm kiế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! - j.c
Cảm ơn bạn đã tìm 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 tất tìm kiếm tất cả các video nhiều gigabyte từ kỳ nghỉ cuối cùng của gia đình, ngay cả khi lệnh dễ gõ hơn. - mightypile


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

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

83
2017-07-31 13:44



dễ nhất, dài dòng, đệ quy và không phân biệt chữ hoa chữ thường. ngón tay cái lên. - Francesco Casula
nếu bạn thêm -A3 thì tốt hơn - albanx
Điều đó thật ngầu. - kodmanyagha


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

Trước hết, tôi tin rằng bạn đã sử dụng -H thay 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 có chứa văn bản cụ thể "Giấy phép Apache" bên trong thư mục của bạn. Nó sẽ hiển thị kết quả tương tự như dưới đây (đầ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" và "TEXT", bạn có thể sử dụng -i chuyển sang 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.


50
2017-11-09 13:18



OP đã yêu cầu các tệp có chứa văn bản trong nội dung của họ chứ không phải tên tệp. - Auxiliary
Đó là những gì lệnh này làm: find sẽ vượt qua 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ế đối với 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
@Auxiliary - 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
@Mene Thật là một trạng thái buồn khi nhận xét của Auxiliary có nhiều phiếu bầu hơn bạn ... ngay cả khi bình luận của họ là từ năm 2014 và của bạn là năm 2017 mà bình luận của họ có 6 khi nó phải có chính xác 0 và bạn chỉ có một (bây giờ là hai) isn Tôi muốn tin điều gì đó. - Pryftan
@Mene Điều đó đang được nói -iname không phân biệt dạng chữ, 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


Nếu là của bạn grep không hỗ trợ tìm kiếm đệ quy, bạn có thể kết hợp find vớ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 ra 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 phân biệt chữ hoa chữ thường
  • -l - chỉ xuất ra tên tệp nơi tìm thấy kết quả phù hợp
  • -h - chỉ xuất ra dòng phù hợp (không phải tên tệp)

47
2018-06-20 08:49



Điều này tương đương với grep 'text-to-find-here' không có tên tệp nếu find không tìm thấy gì cả. Điều này sẽ treo và chờ cho người dùng nhập vào! Thêm vào --no-run-if-empty như một tùy chọn để xargs. - hagello
Sự kết hợp tìm kiếm 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 dấu cách (các ký tự xargs diễn giải dưới dạng dấu tách). Sử dụng find … -exec grep … +. Nếu bạn nhấn mạnh vào việc sử dụng tìm kiếm cùng với xargs, hãy sử dụng -print0 và -0. - hagello


grep -insr "pattern" *
  • i: Bỏ qua phân biệt chữ hoa trong cả hai tệp PATTERN và tệp đầu vào.
  • n: Tiền tố mỗi dòng đầu ra với số dòng 1 dựa trên tệp đầu vào của nó.
  • s: Loại bỏ thông báo lỗi về các tệp không tồn tại hoặc không đọc được.
  • r: Đọc tất cả các tệp theo từng thư mục, đệ quy.

34
2018-02-26 05:47



Bạn có thể giải thích câu trả lời của bạn được cải thiện như thế nào dựa trên các câu trả lời khác hoặc cách câu trả lời đó khác với chúng? - Amos M. Carpenter
không phức tạp để 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ẽ thực hiện tìm kiếm đệ quy vv) và sử dụng "*" ở cuối sẽ tìm kiếm tất cả các thư mục (không cần chỉ định bất kỳ đường dẫn hoặc tên thư mục). - enfinet
Xin lỗi, tôi nên rõ ràng hơn: nó sẽ là tuyệt vời nếu bạn có thể bao gồm lời giải thích đó trong câu trả lời của bạn. Vì nó là viết tắt, đặc biệt là với rất nhiều câu trả lời tương tự khác đã được, thật khó để nhìn thấy từ một câu trả lời ngắn như vậy những gì lợi ích của cố gắng nó qua câu trả lời được chấp nhận hoặc một trong những câu trả lời được bình chọn sẽ là. - Amos M. Carpenter
Đây là câu trả lời hay + giải thích tốt - khelili miliana
@ AmosM.Carpenter Một điều tôi thích về câu trả lời này là chỉ ra các đối số đàn áp, có thể giúp lọc ra tiếng ồn mà không quan trọng để nhận được kết quả chúng tôi thực sự muốn. Grep in các lỗi như "Hàm 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


grep (GNU hoặc là BSD)

Bạn có thể dùng grep công cụ tìm kiếm đệ quy thư mục hiện tại, như:

grep -r "class foo" .

Chú thích: -r - Recursively tìm kiếm thư mục con.

Bạn cũng có thể sử dụng cú pháp globbing để 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 globbing (**), nó quét tất cả các tệp đệ 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 gặp lỗi mà đố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 find thay vào đó, chẳng hạn như:

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 ripgrep thay vào đó, 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.

Nó nhanh hơn nhiều so với bất kỳ công cụ nào khác như GNU/BSD  grep, ucg, ag, sift, ack, pt hoặc tương tự, vì nó được xây dựng trên đầu trang của Động cơ regex của Rust trong đó sử dụng tự động hữu hạn, SIMD và tối ưu hóa chữ tích cực để thực hiện tìm kiếm rất nhanh.

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


Bạn có thể sử dụng các thông số chung như:

  • -i - Tìm kiếm không nhạy cảm.
  • -I - Bỏ qua các tập tin nhị phân.
  • -w - Tìm kiếm toàn bộ các từ (trái ngược với từ khớp một phần).
  • -n - Hiển thị các dòng của trận đấu của bạn.
  • -C/--context (ví dụ. -C5) - Tăng bối 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 tin mà văn bản được tìm thấy.
  • -c - Hiển thị số dòng phù hợp. Có thể được kết hợp với -H.

29
2018-05-09 10:11



Tôi cũng tìm thấy globbing mở rộng hữu ích. Nhưng hãy nhớ rằng nếu có số lượng tệp rất lớn, bạn có thể gặp lỗi "Danh sách đối số quá dài". (Đơn giản globbing cũng dễ bị loại lỗi). - Yoory N.


Thử:

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

24
2017-12-10 05:47



Đây thực sự là một ví dụ điển hình khi KHÔNG sử dụng xargs như thế .. 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 . Các xargs ở đây khớp với tệp WRONG và KHÔNG khớp với tệp mong muốn. Sử dụng một find .. -print0 | xargs -0 ... nhưng đó là việc sử dụng ống hoặc sử dụng vô dụng find ... -exec grep ... {} + - shalomb