Sử dụng cú pháp grep --exclude / - bao gồm để không grep qua các tệp nhất định


780

Tôi đang tìm chuỗi foo=trong tệp văn bản trong cây thư mục. Đó là trên một máy Linux thông thường, tôi có bash shell:

grep -ircl "foo=" *

Trong các thư mục cũng có nhiều tệp nhị phân khớp với "foo =". Vì các kết quả này không liên quan và làm chậm quá trình tìm kiếm, tôi muốn grep bỏ qua việc tìm kiếm các tệp này (chủ yếu là hình ảnh JPEG và PNG). Làm thế nào tôi có thể làm điều đó?

Tôi biết có các tùy chọn --exclude=PATTERN--include=PATTERN, nhưng định dạng mẫu là gì? Trang người đàn ông của grep nói:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

Tìm kiếm trên grep bao gồm , grep bao gồm loại trừ , loại trừ grep và các biến thể không tìm thấy bất cứ điều gì có liên quan

Nếu có một cách tốt hơn để chỉ grepping trong một số tệp nhất định, tôi sẽ làm tất cả cho nó; di chuyển các tập tin vi phạm không phải là một lựa chọn. Tôi không thể chỉ tìm kiếm một số thư mục nhất định (cấu trúc thư mục là một mớ hỗn độn lớn, với mọi thứ ở mọi nơi). Ngoài ra, tôi không thể cài đặt bất cứ thứ gì, vì vậy tôi phải làm với các công cụ phổ biến (như grep hoặc tìm thấy được đề xuất ).


13
Chỉ cần FYI, các đối số được sử dụng: -c đếm các trận đấu trong tệp -i không phân biệt chữ hoa chữ thường -l chỉ hiển thị các tệp trùng khớp -r đệ quy
Piskvor rời khỏi tòa nhà

68
Một cách nhanh hơn để loại trừ các thư mục svn là --exclude-dir=.svn, vì vậy grep hoàn toàn không đi vào chúng
orip

25
Một vài điểm phạm vi mà mọi người có thể cần biết: 1. Lưu ý việc thiếu dấu ngoặc kép trên toàn cầu ở đây: --exclude = ' . {Png, jpg}' không hoạt động (ít nhất là với phiên bản GNU grep của tôi) vì grep không hỗ trợ {} trong các khối của nó. Ở trên được mở rộng shell thành '--exclude = .png --exclude = *. Jpg' (giả sử không có tệp nào khớp trong cwd - rất khó xảy ra vì bạn thường không bắt đầu tên tệp bằng '--exclude =') grep thích tốt 2. --exclude là một phần mở rộng GNU và không phải là một phần của định nghĩa grep của POSIX, vì vậy nếu bạn viết tập lệnh bằng cách này, hãy lưu ý rằng chúng sẽ không nhất thiết phải chạy trên các hệ thống không phải GNU.
ijw

2
Ví dụ đầy đủ về việc sử dụng loại trừ-dir:grep -r --exclude-dir=var "pattern" .
Tisch

Câu trả lời:


767

Sử dụng cú pháp toàn cầu shell:

grep pattern -r --include=\*.{cpp,h} rootdir

Cú pháp cho --excludegiống hệt nhau.

Lưu ý rằng ngôi sao được thoát bằng dấu gạch chéo ngược để ngăn nó bị mở rộng bởi lớp vỏ (trích dẫn nó, chẳng hạn như --include="*.{cpp,h}", cũng sẽ hoạt động tốt). Mặt khác, nếu bạn có bất kỳ tệp nào trong thư mục làm việc hiện tại khớp với mẫu, dòng lệnh sẽ mở rộng thành một cái gì đó giống như grep pattern -r --include=foo.cpp --include=bar.h rootdir, nó sẽ chỉ tìm kiếm các tệp có tên foo.cppbar.h, rất có thể không phải là thứ bạn muốn.


8
Tôi không biết tại sao, nhưng tôi đã phải trích dẫn mẫu bao gồm như thế này:grep pattern -r --include="*.{cpp,h}" rootdir
topek

6
@topek: Điểm hay - nếu bạn có bất kỳ tệp .cpp / .h nào trong thư mục hiện tại của mình, thì trình bao sẽ mở rộng toàn cầu trước khi gọi grep, vì vậy bạn sẽ kết thúc bằng một dòng lệnh như grep pattern -r --include=foo.cpp --include=bar.h rootdir, sẽ chỉ tìm kiếm các tệp đặt tên foo.cpphay bar.h. Nếu bạn không có bất kỳ tệp nào khớp với toàn cầu trong thư mục hiện tại, thì shell sẽ chuyển trên toàn cầu sang grep, điều này diễn giải chính xác.
Adam Rosenfield

6
Tôi chỉ nhận ra rằng toàn cầu được sử dụng để chỉ khớp với tên tệp. Để loại trừ toàn bộ thư mục một --exclude-dirtùy chọn cần . Quy tắc tương tự áp dụng mặc dù. Chỉ tên tệp thư mục được khớp, không phải là một đường dẫn.
Krzysztof Jabłoński

3
--includedường như không hoạt động sau --exclude. Tôi cho rằng thậm chí không có ý nghĩa gì khi thử, ngoại trừ việc tôi phải aliasgrep với một danh sách dài --exclude--exclude-dir, mà tôi sử dụng để tìm kiếm mã, bỏ qua các thư viện và trao đổi tệp và mọi thứ. Tôi sẽ đã hy vọng rằng grep -r --exclude='*.foo' --include='*.bar'sẽ làm việc, vì vậy tôi có thể hạn chế của tôi aliasđể --include='*.bar'chỉ, nhưng nó dường như bỏ qua --includevà bao gồm tất cả những gì không phải là một tập tin .foo. Trao đổi thứ tự --include--excludehoạt động, nhưng than ôi, điều đó không hữu ích với tôi alias.
Michael Scheper

1
Làm thế nào chúng ta có thể đọc được suy nghĩ của ai đó để có được quy tắc cho việc này PATTERN. Nửa giờ tôi không thể tìm thấy bất kỳ mô tả nào về những gì họ đang chờ đợi ở đó
Arkady

221

Nếu bạn chỉ muốn bỏ qua các tệp nhị phân, tôi khuyên bạn nên xem -Itùy chọn (chữ hoa i). Nó bỏ qua các tập tin nhị phân. Tôi thường xuyên sử dụng lệnh sau:

grep -rI --exclude-dir="\.svn" "pattern" *

Nó tìm kiếm đệ quy, bỏ qua các tệp nhị phân và không tìm trong các thư mục ẩn Subversion, cho bất kỳ mẫu nào tôi muốn. Tôi có bí danh là "grepsvn" trên hộp của tôi tại nơi làm việc.


1
Cảm ơn, điều đó rất hữu ích cho một số tình huống khác mà tôi gặp phải.
Piskvor rời khỏi tòa nhà

25
--exclude-dirkhông có sẵn ở khắp mọi nơi. hộp RH của tôi đang hoạt động với GNU grep 2.5.1 không có nó.
gcb

Bất kỳ đề xuất cho những gì để sử dụng khi --exclude-dirkhông có sẵn? Trong tất cả các quan điểm của tôi, --excludedường như không phù hợp với dự luật.
JMTyler

Bạn luôn có thể tải xuống nguồn grep mới nhất từ ​​GNU và thực hiện cấu hình '; làm; sudo thực hiện cài đặt '. Đây là một trong những điều đầu tiên tôi làm trên bản phân phối Linunx của Mac hoặc cũ hơn.
Jonathan Hartley

3
Chính xác những gì tôi cần. Thật ra, tôi dùng git. Vì vậy, --exclude-dir="\.git". :-)
Ionică Bizău

66

Xin hãy xem ack , được thiết kế cho chính xác những tình huống này. Ví dụ của bạn về

grep -ircl --exclude=*.{png,jpg} "foo=" *

được thực hiện với ack như

ack -icl "foo="

bởi vì ack không bao giờ tìm trong các tệp nhị phân theo mặc định và -r được bật theo mặc định. Và nếu bạn chỉ muốn tập tin CPP và H, thì hãy làm

ack -icl --cpp "foo="

Có vẻ tốt, sẽ thử phiên bản Perl độc lập vào lần tới, cảm ơn.
Piskvor rời khỏi tòa nhà

5
Cuộc gọi tốt, tôi không còn có thể sống mà không có ack.
Cơ hội

1
stackoverflow.com/questions/667471/ trộm - Điều này sẽ cho phép bạn nhận ack trên windows, nếu đó là nơi bạn đang chạy grep từ đó.
TamusJRoyce

@Chance Có thể bạn muốn silversearcher-ag , chỉ apt-gettrong Ubuntu :)
Justme0

đừng nhầm lẫn vớiawk
jasonleonhard

35

grep 2.5.3 đã giới thiệu tham số --exclude-dir sẽ hoạt động theo cách bạn muốn.

grep -rI --exclude-dir=\.svn PATTERN .

Bạn cũng có thể đặt biến môi trường: GREP_OPTIONS = "- loại trừ-dir = .svn"

Tôi sẽ bình chọn thứ hai cho Andy cho ack , mặc dù vậy, đó là thứ tốt nhất.


7
+1 để đề cập đến số phiên bản chính xác; Tôi có grep 2.5.1 và tùy chọn loại trừ-dir không khả dụng
James

25

Tôi đã tìm thấy điều này sau một thời gian dài, bạn có thể thêm nhiều bao gồm và loại trừ như:

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js

5
Tốt hơn là kết hợp chúng trong một danh sách như: --exclude = {pattern1, pattern2, pattern3}
Yasser Sinjab

12

Lệnh được đề xuất:

grep -Ir --exclude="*\.svn*" "pattern" *

là sai về mặt khái niệm, bởi vì --exclude hoạt động trên tên cơ sở. Nói cách khác, nó sẽ chỉ bỏ qua .svn trong thư mục hiện tại.


3
Đúng, nó hoàn toàn không hoạt động đối với tôi. Công cụ phù hợp với tôi là: loại trừ-dir = .svn
Taryn East

2
@Nicola cảm ơn bạn! Tôi đã xé tóc ra về lý do tại sao điều này sẽ không hoạt động. Nói cho tôi biết, có cách nào để khám phá điều này từ trang chủ không? Tất cả những gì nó nói là nó phù hợp với "THỰC HIỆN". Trang web EDIT nói "tập tin", như được giải thích ở đây fixunix.com/unix/iêng
13ren

11

Trong grep 2.5.1, bạn phải thêm dòng này vào hồ sơ ~ / .bashrc hoặc ~ / .bash

export GREP_OPTIONS="--exclude=\*.svn\*"

9

Đôi khi tôi thấy đầu ra của grep rất hữu ích:

grep -rn "foo=" . | grep -v "Binary file"

Mặc dù vậy, điều đó không thực sự ngăn nó tìm kiếm các tệp nhị phân.


10
Bạn có thể sử dụng grep -Iđể bỏ qua các tệp nhị phân.
Nathan Fellman

cũng đã làm điều đó khi tôi còn trẻ ... bây giờ tôi biết rõ hơn và khi gặp phải một vấn đề, điều đầu tiên là RTFM
gcb

grepping grep sẽ loại bỏ các màu nổi bật.
Tối đa

7

Nếu bạn không phản đối việc sử dụng find, tôi thích -prunetính năng của nó :

find [directory] \
        -name "pattern_to_exclude" -prune \
     -o -name "another_pattern_to_exclude" -prune \
     -o -name "pattern_to_INCLUDE" -print0 \
| xargs -0 -I FILENAME grep -IR "pattern" FILENAME

Trên dòng đầu tiên, bạn chỉ định thư mục bạn muốn tìm kiếm. .(thư mục hiện tại) là một đường dẫn hợp lệ, ví dụ.

Vào ngày 2 và dòng thứ 3, sử dụng "*.png", "*.gif", "*.jpg", và vân vân. Sử dụng nhiều -o -name "..." -prunecấu trúc như bạn có các mẫu.

Trên dòng thứ 4, bạn cần một dòng khác -o(nó chỉ định "hoặc" đến find), các mẫu bạn muốn và bạn cần một -printhoặc -print0ở cuối của nó. Nếu bạn chỉ muốn "mọi thứ khác" còn lại sau khi cắt tỉa *.gif, *.pngvv hình ảnh, sau đó sử dụng -o -print0và bạn đã hoàn tất với dòng thứ 4.

Cuối cùng, trên dòng thứ 5 là đường ống xargslấy từng tệp kết quả đó và lưu trữ chúng trong một biến FILENAME. Sau đó, nó vượt qua grepcác -IRcờ, "pattern"và sau đó FILENAMEđược mở rộng xargsđể trở thành danh sách tên tệp được tìm thấy bởi find.

Đối với câu hỏi cụ thể của bạn, tuyên bố có thể trông giống như:

find . \
     -name "*.png" -prune \
     -o -name "*.gif" -prune \
     -o -name "*.svn" -prune \
     -o -print0 | xargs -0 -I FILES grep -IR "foo=" FILES


Một sửa đổi tôi muốn đề xuất: bao gồm -falsengay lập tức sau mỗi lần -prunequên sử dụng -print0hoặc một loại execlệnh nào đó sẽ không thực sự in các tệp bạn muốn loại trừ: -name "*.png" -prune -false -o name "*.gif -prune -false...
OnlineCop

7

Trên CentOS 6.6 / Grep 2.6.3, tôi phải sử dụng nó như thế này:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

Chú ý việc thiếu dấu bằng "=" (nếu không --include, --exclude, include-dir--exclude-dirđược bỏ qua)


6

git grep

Sử dụng git grepđược tối ưu hóa cho hiệu suất và nhằm mục đích tìm kiếm thông qua các tập tin nhất định.

Theo mặc định, nó bỏ qua các tệp nhị phân và nó đang tôn vinh bạn .gitignore. Nếu bạn không làm việc với cấu trúc Git, bạn vẫn có thể sử dụng nó bằng cách chuyển --no-index.

Cú pháp ví dụ:

git grep --no-index "some_pattern"

Để biết thêm ví dụ, xem:


5

Tôi là một phạm nhân, được cấp, nhưng đây là cách ~ / .bash_profile của tôi trông:

xuất GREP_OPTIONS = "- orl --exclude-dir = .svn --exclude-dir = .cache --color = auto" GREP_COLOR = '1; 32'

Lưu ý rằng để loại trừ hai thư mục, tôi phải sử dụng --exclude-dir hai lần.



3

Nếu bạn tìm kiếm không đệ quy, bạn có thể sử dụng các mẫu glop để khớp với tên tệp.

grep "foo" *.{html,txt}

bao gồm html và txt. Nó chỉ tìm kiếm trong thư mục hiện tại.

Để tìm kiếm trong thư mục con:

   grep "foo" */*.{html,txt}

Trong các tiểu ngành:

   grep "foo" */*/*.{html,txt}

3

Trong các thư mục cũng có nhiều tệp nhị phân. Tôi không thể chỉ tìm kiếm một số thư mục nhất định (cấu trúc thư mục là một mớ hỗn độn lớn). Có cách nào tốt hơn để chỉ grepping trong một số tập tin nhất định?

ripgrep

Đây là một trong những công cụ nhanh nhất được thiết kế để tìm kiếm đệ quy thư mục hiện tại của bạn. Nó được viết bằng Rust , được xây dựng trên đỉnh công cụ regex của Rust để đạt hiệu quả tối đa. Kiểm tra phân tích chi tiết tại đây .

Vì vậy, bạn chỉ có thể chạy:

rg "some_pattern"

Nó tôn trọng .gitignorevà tự động bỏ qua các tập tin / thư mục ẩn và tập tin nhị phân.

Bạn vẫn có thể tùy chỉnh bao gồm hoặc loại trừ các tệp và thư mục bằng -g/ --glob. Quy tắc Globbing phù hợp với ảm đạm .gitignore. Kiểm tra man rggiúp đỡ.

Để biết thêm ví dụ, hãy xem: Làm cách nào để loại trừ một số tệp không khớp với các tiện ích mở rộng nhất định với grep?

Trên macOS, bạn có thể cài đặt qua brew install ripgrep.


3

tìm và xargs là bạn bè của bạn. Sử dụng chúng để lọc danh sách tệp thay vì grep's --exclude

Hãy thử một cái gì đó như

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="

Ưu điểm của việc làm quen với điều này là nó có thể mở rộng sang các trường hợp sử dụng khác, ví dụ để đếm các dòng trong tất cả các tệp không phải png:

find . -not -name '*.png' -o -type f -print | xargs wc -l

Để xóa tất cả các tệp không png:

find . -not -name '*.png' -o -type f -print | xargs rm

Vân vân.

Như đã chỉ ra trong các bình luận, nếu một số tệp có thể có khoảng trắng trong tên của chúng, hãy sử dụng -print0xargs -0thay vào đó.


1
Điều này không hoạt động trên tên tệp có dấu cách, nhưng vấn đề đó được giải quyết dễ dàng bằng cách sử dụng print0 thay vì in và thêm tùy chọn -0 vào xargs.
Adam Rosenfield

2

những kịch bản đó không hoàn thành tất cả vấn đề ... Hãy thử điều này tốt hơn:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

kịch bản này tốt hơn, bởi vì nó sử dụng các biểu thức chính quy "thực" để tránh các thư mục tìm kiếm. chỉ tách riêng tên thư mục hoặc tệp với "\ |" trên grep -v

thưởng thức nó tìm thấy trên vỏ linux của tôi! XD


2

Nhìn @ cái này.

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags

2
Những điều đạt được khoảng này đã được đề cập trong các bài viết khác; những gì nhiều hơn, điều này là sai, trong đó với các tùy chọn bố cục khác nhau, nó sẽ làm rối loạn số dòng và những thứ tương tự hoặc loại trừ các dòng bối cảnh mong muốn.
Chris Morgan

Làm thế nào bạn có thể sử dụng một số tùy chọn "-v" cùng một lúc?
Mở đường

1

Các --binary-files=without-matchtùy chọn để GNU grepđược nó để bỏ qua tập tin nhị phân. (Tương đương với công -Itắc được đề cập ở nơi khác.)

(Điều này có thể yêu cầu một phiên bản gần đây của grep; ít nhất là 2.5.3.)


1

thích hợp cho tập tin tcsh .alias:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

Mất một lúc tôi mới nhận ra rằng phần {mm, m, h, cc, c} KHÔNG nên nằm trong dấu ngoặc kép. ~ Keith


0

Để bỏ qua tất cả các kết quả nhị phân từ grep

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

Phần awk sẽ lọc tất cả các tệp nhị phân foo khớp với các dòng


-2

Thử cái này:

  1. Tạo một thư mục có tên " --F" theo dòng điện .. (hoặc liên kết một thư mục khác được đổi tên thành " --F" tức là double-minus-F.
  2. #> grep -i --exclude-dir="\-\-F" "pattern" *
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.