Làm thế nào tôi có thể loại trừ các thư mục từ grep -R?


667

Tôi muốn duyệt qua tất cả các thư mục con, ngoại trừ thư mục "node_modules".



14
Chỉ cần gõ "man grep" và bạn sẽ thấy các tùy chọn --exclude và --exclude-dir được liệt kê ngay tại đó - từ tiêu đề của câu hỏi này, tôi giả sử bạn đã biết về grep ...
arcseldon

34
Nếu bạn đang grepping cho mã trong kho git và node_moduleslà của bạn .gitignore, git grep "STUFF"là cách dễ nhất. git greptìm kiếm các tệp được theo dõi trong cây làm việc, bỏ qua mọi thứ từ.gitignore
0xcaff

2
Một ví dụ cho nút: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- hơn nữa bạn luôn có thể đặt bí danh này trong trình bao để 'gật đầu' hoặc bất cứ điều gì và sử dụng một đối số lệnh làm đầu vào chuỗi ..
bshea

Câu trả lời:


394

GIẢI PHÁP 1 (kết hợp findgrep)

Mục đích của giải pháp này không phải là để giải quyết grephiệu năng mà là để hiển thị một giải pháp di động: cũng nên hoạt động với phiên bản busybox hoặc GNU cũ hơn 2.5.

Sử dụng find, để loại trừ thư mục foo và thanh:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

Sau đó kết hợp findvà sử dụng không đệ quy grep, như một giải pháp di động:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

GIẢI PHÁP 2 (sử dụng đệ quy grep):

Bạn đã biết giải pháp này rồi, nhưng tôi thêm nó vì đây là giải pháp hiệu quả và mới nhất. Lưu ý đây là một giải pháp ít di động nhưng dễ đọc hơn cho con người.

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Để loại trừ nhiều thư mục, sử dụng --exclude-dirnhư:

--exclude-dir={node_modules,dir1,dir2,dir3}

GIẢI PHÁP 3 (Ag)

Nếu bạn thường xuyên tìm kiếm thông qua mã, Ag (Trình tìm kiếm bạc) là một thay thế nhanh hơn nhiều so với grep, đó là tùy chỉnh để tìm kiếm mã. Chẳng hạn, nó tự động bỏ qua các tệp và thư mục được liệt kê trong .gitignore, vì vậy bạn không phải tiếp tục chuyển các tùy chọn loại trừ rườm rà tương tự sang grephoặc find.


2
sự kết hợp này tìm kiếm nhanh hơn --exclude-dir=dirvà nó hiển thị kết quả với màu sắc - dễ đọc
Maxim Yefremov

27
"Sự kết hợp này" find ... -execkhông nhanh hơn grep --exclude-dirđối với tôi. Lợi thế rất lớn đối với grep (nhanh hơn khoảng năm lần với các tệp 26k +, được lọc ra khỏi 38k + trên ổ cứng), trừ khi bạn thay thế \;bằng +kết hợp find / exec. Sau đó, grep "chỉ" nhanh hơn khoảng 30%. Cú pháp grep cũng dễ đọc của con người :).
Kjell Andreassen

Đồng ý, vì điều này là hiển nhiên. Một số busybox không có lệnh GREP.
hornetbzz

10
cũng lưu ý rằng bạn có thể loại trừ nhiều với--exclude-dir={dir1,dir2}
suh

4
Tôi không ngạc nhiên chút nào đó node_moduleslà ví dụ kinh điển.
pdoherty926

981

Các phiên bản gần đây của GNU Grep (> = 2.5.2 ) cung cấp:

--exclude-dir=dir

trong đó loại trừ các thư mục phù hợp với mẫu dirtừ các tìm kiếm thư mục đệ quy.

Vì vậy, bạn có thể làm:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

Để biết thêm một chút thông tin về cú pháp và cách sử dụng, xem

Đối với GNU Greps và POSIX Grep cũ hơn , hãy sử dụng findnhư được đề xuất trong các câu trả lời khác.

Hoặc chỉ cần sử dụng ack( Chỉnh sửa : hoặc Trình tìm kiếm bạc ) và được thực hiện với nó!


4
@Manocho: Nếu bạn nghĩ acklà tuyệt vời, hãy thử The Silver Searcher và xem tốc độ tăng lên!
Johnsyweb

30
Cú pháp cho người thiếu kiên nhẫn: --exclude-dir=dirsử dụng grepcác mẫu biểu thức chính quy, không phải tập tin toàn cầu của shell. Các mẫu làm việc trên các đường dẫn liên quan đến thư mục hiện tại của bạn. Vì vậy, sử dụng mô hình --exclude-dir=dir, không --exclude-dir="/root/dir/*".
tanius

15
Nếu bạn muốn loại trừ nhiều thư mục khỏi tìm kiếm, có lựa chọn nào tốt hơn là sử dụng : $ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir?
Darshan Chaudhary

4
Tôi có lẽ đã dành quá nhiều thời gian cho việc này hơn bất kỳ người tỉnh táo nào, nhưng tôi không thể tìm ra cách loại trừ một thư mục con khỏi tìm kiếm - grep -r --exclude-dir=public keyword .hoạt động, nhưng grep -r --exclude-dir='public/dist' keyword .không. Tôi đã thử thêm các ký tự đại diện regex, thoát các ký tự, v.v., nhưng dường như không có gì giúp được.
dkobozev

72
Loại trừ nhiều thư mục như vậy:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97

77

Nếu bạn muốn loại trừ nhiều thư mục :

"r" cho đệ quy, "l" để chỉ in tên của các tệp chứa kết quả khớp và "i" để bỏ qua phân biệt trường hợp:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

Ví dụ: Tôi muốn tìm các tệp có chứa từ 'xin chào'. Tôi muốn tìm kiếm trong tất cả các thư mục linux của tôi ngoại trừ thư mục Proc , thư mục khởi động , thư mục sys và thư mục gốc :

grep -rli --exclude-dir={proc,boot,root,sys} hello /

Lưu ý: Ví dụ trên cần được root

Lưu ý 2 (theo @skplunkerin): không thêm dấu cách sau dấu phẩy trong {dir1,dir2,dir3}


5
LƯU Ý: không thêm dấu cách sau dấu phẩy trong{dir1,dir2,dir3}
skplunkerin

Cảm ơn, tiện dụng khi chuyển qua không gian làm việc SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237

1
Bạn chỉ có thể cung cấp --exclude-dirtùy chọn nhiều lần.
Walf

44

Cú pháp này

--exclude-dir={dir1,dir2}

được mở rộng bởi shell (ví dụ Bash), chứ không phải bởi grep, vào đây:

--exclude-dir=dir1 --exclude-dir=dir2

Trích dẫn sẽ ngăn vỏ mở rộng nó, vì vậy điều này sẽ không hoạt động:

--exclude-dir='{dir1,dir2}'    <-- this won't work

Các mẫu được sử dụng --exclude-dircùng loại mẫu được mô tả trong trang man cho --excludetùy chọn:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

Shell thường sẽ cố gắng mở rộng một mẫu như vậy, vì vậy để tránh điều này, bạn nên trích dẫn nó:

--exclude-dir='dir?'

Bạn có thể sử dụng dấu ngoặc nhọn và trích dẫn các mẫu loại trừ như thế này:

--exclude-dir={'dir?','dir??'}

Một mẫu có thể trải rộng trên nhiều phân đoạn đường dẫn:

--exclude-dir='some*/?lse'

Điều này sẽ loại trừ một thư mục như topdir/something/else.


13

Thường xuyên sử dụng này:

grepcó thể được sử dụng cùng với -r(đệ quy), i(trường hợp bỏ qua) và -o(chỉ in một phần của dòng). Để loại trừ filessử dụng --excludevà để loại trừ sử dụng thư mục --exclude-dir.

Đặt nó lại với nhau, bạn kết thúc với một cái gì đó như:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

Mô tả nó làm cho âm thanh phức tạp hơn nhiều so với thực tế. Dễ dàng hơn để minh họa với một ví dụ đơn giản.

Thí dụ:

Giả sử tôi đang tìm kiếm dự án hiện tại cho tất cả các nơi tôi đặt giá trị chuỗi rõ ràng debuggertrong phiên gỡ lỗi và bây giờ muốn xem lại / xóa.

Tôi viết một kịch bản được gọi findDebugger.shvà sử dụng grepđể tìm tất cả các lần xuất hiện. Tuy nhiên:

Đối với loại trừ tệp - Tôi muốn đảm bảo rằng .eslintrcbị bỏ qua (điều này thực sự có một quy tắc linting về debuggervì vậy nên được loại trừ). Tương tự như vậy, tôi không muốn kịch bản của riêng mình được tham chiếu trong bất kỳ kết quả nào.

Đối với loại trừ thư mục - Tôi muốn loại trừ node_modulesvì nó chứa rất nhiều thư viện tham chiếu debuggervà tôi không quan tâm đến những kết quả đó. Ngoài ra, tôi chỉ muốn bỏ qua .idea.gitẩn các thư mục vì tôi cũng không quan tâm đến các vị trí tìm kiếm đó và muốn giữ hiệu suất tìm kiếm.

Vì vậy, đây là kết quả - Tôi tạo một tập lệnh được gọi findDebugger.shvới:

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .

Tôi tin rằng tùy chọn "r" nên được in bằng chữ in hoa "-R".
hornetbzz

1
Hấp dẫn. "R" đã luôn làm việc cho tôi trên nix và mac.
arcseldon

Khi tôi viết câu trả lời của mình , tôi đã sử dụng -R(tôi không nhớ tại sao bây giờ). Tôi thường sử dụng -r. Nó chỉ ra rằng phiên bản chữ hoa đi theo symlink . GẠCH
Johnsyweb

@Johnsyweb - cảm ơn. nâng cao câu trả lời của bạn - không nhớ lại khi nào, có thể vào năm 2016 khi tôi thêm câu này :)
arcseldon

10

Bạn có thể thử một cái gì đó như grep -R search . | grep -v '^node_modules/.*'


34
Không phải là một giải pháp tốt trong một số trường hợp. Ví dụ: Nếu thư mục 'node_modules' là một thư mục lớn có nhiều kết quả dương tính giả (do đó cần phải lọc ra thư mục) thì grep đầu tiên đang lãng phí rất nhiều thời gian để tìm kiếm qua thư mục con và THEN bộ lọc grep thứ hai ra trận đấu Sẽ nhanh hơn để loại trừ node_modules trong chính grep đầu tiên.
Giáo sư

2
Tôi không quan tâm đến sự chậm chạp, tôi có thể nhìn vào lệnh và biết nó làm gì
Funkodebat

1
Ditto cho nhận xét của Guru. Một grep /varbị treo khi nó xảy ra /var/runtrong trường hợp của tôi. Do đó lý do tôi muốn tránh thư mục ở nơi đầu tiên.
jww

3
--exclude-dirlà giải pháp tốt nhất tính đến năm 2016.
Omar Tariq

10

Nếu bạn đang grepping cho mã trong kho git và node_modulestrong của bạn .gitignore, bạn có thể sử dụng git grep. git greptìm kiếm các tệp được theo dõi trong cây làm việc, bỏ qua mọi thứ từ.gitignore

git grep "STUFF"

Đây là mẹo rất hữu ích. Cảm ơn.
NKM

4

Rất hữu ích, đặc biệt đối với những người giao dịch với Node.js nơi chúng tôi muốn tránh tìm kiếm bên trong "node_modules":

find ./ -not -path "*/node_modules/*" -name "*.js" | xargs grep keyword

2

Một lệnh làm việc đơn giản:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

Ở trên tôi grep cho văn bản "creativecommons.org" trong thư mục hiện tại "dspace" và loại trừ các thư mục {log, propertystore}.

Làm xong.


Gọn gàng, bao gồm một số thư mục trong ngoặc
Mijo

2

Nhiều câu trả lời đúng đã được đưa ra ở đây, nhưng tôi thêm câu này để nhấn mạnh một điểm khiến một số nỗ lực vội vã thất bại trước đây: exclude-dirlấy một mẫu , không phải là đường dẫn đến một thư mục.

Nói rằng tìm kiếm của bạn là:

grep -r myobject

Và bạn nhận thấy rằng đầu ra của bạn lộn xộn với kết quả từ src/other/objects-folder. Lệnh này sẽ không cung cấp cho bạn kết quả dự định:

grep -r myobject --exclude-dir=src/other/objects-folder

Và bạn có thể tự hỏi tại sao exclude-dirkhông làm việc! Để thực sự loại trừ kết quả khỏi objects-folder, chỉ cần làm điều này:

grep -r myobject --exclude-dir=objects-folder

Nói cách khác, chỉ cần sử dụng tên thư mục , không phải đường dẫn. Rõ ràng một khi bạn biết điều đó.

Từ trang người đàn ông:

--exclude-dir = GLOB
Bỏ qua mọi thư mục dòng lệnh có hậu tố tên khớp với mẫu GLOB. Khi tìm kiếm đệ quy, bỏ qua mọi thư mục con có tên cơ sở khớp với GLOB. Bỏ qua mọi dấu gạch chéo thừa trong GLOB.


2

Cái này hoạt động với tôi:

grep <stuff> -R --exclude-dir=<your_dir>

5
Câu trả lời này khác với những gì đã được đăng như thế nào?
aexl


-1

Một cách đơn giản hơn là lọc kết quả của bạn bằng cách sử dụng "grep -v".

grep -i needle -R * | grep -v node_modules


12
Đây thực sự là câu trả lời tương tự DipSwitch cung cấp 3 năm trước đó. Nó có cùng một vấn đề, quá.
jww
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.