ฉันจะแยกไดเรกทอรีออกจาก grep -R ได้อย่างไร


669

ฉันต้องการสำรวจไดเรกทอรีย่อยทั้งหมดยกเว้นไดเรกทอรี "node_modules"



14
เพียงพิมพ์ "man grep" แล้วคุณจะเห็น --exclude และ --exclude-dir options ที่แสดงอยู่ตรงนี้ - จากส่วนหัวของคำถามนี้ฉันคาดว่าคุณรู้เรื่อง grep แล้ว ...
arcseldon

35
หากคุณกำลัง grepping รหัสในพื้นที่เก็บข้อมูลคอมไพล์และnode_modulesอยู่ในของคุณ.gitignore, git grep "STUFF"เป็นวิธีที่ง่าย git grepค้นหาไฟล์ที่ถูกติดตามใน.gitignore
แผนผัง

2
ตัวอย่างสำหรับโหนด: grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"- นอกจากนี้คุณยังสามารถใช้นามแฝงนี้ในเชลล์เพื่อ 'nodegrep' หรืออะไรก็ตามและใช้อาร์กิวเมนต์คำสั่งเป็นอินพุตสตริง ..
bshea

คำตอบ:


394

โซลูชัน 1 (รวมfindและgrep)

วัตถุประสงค์ของการแก้ปัญหานี้ไม่ได้เพื่อจัดการกับgrepประสิทธิภาพ แต่เพื่อแสดงโซลูชั่นแบบพกพา: ควรทำงานกับ busybox หรือ GNU เวอร์ชั่นเก่ากว่า 2.5

ใช้findสำหรับยกเว้นไดเรกทอรี foo และ bar:

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

จากนั้นรวมfindและการใช้แบบไม่เรียกซ้ำในgrepฐานะโซลูชันพกพา:

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

โซลูชัน 2 (ใช้ซ้ำgrep):

คุณรู้วิธีแก้ไขปัญหานี้อยู่แล้ว แต่ฉันเพิ่มเนื่องจากเป็นโซลูชันล่าสุดและมีประสิทธิภาพ หมายเหตุนี่เป็นวิธีการแก้ปัญหาแบบพกพาที่น้อยกว่า แต่มนุษย์อ่านได้มากขึ้น

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

หากต้องการยกเว้นหลายไดเรกทอรีให้ใช้--exclude-dir:

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

โซลูชัน 3 (Ag)

หากคุณค้นหารหัสบ่อยๆAg (The Silver Searcher)เป็นทางเลือกที่รวดเร็วกว่า grep มากซึ่งเป็นรหัสที่กำหนดเองสำหรับการค้นหา ยกตัวอย่างเช่นมันโดยอัตโนมัติละเว้นไฟล์และไดเรกทอรีที่ระบุไว้ใน.gitignoreเพื่อให้คุณไม่ต้องให้ผ่านยุ่งยากเดียวกันยกเว้นตัวเลือกให้หรือgrepfind


2
ชุดค่าผสมนี้ค้นหาเร็วกว่า--exclude-dir=dirและจะแสดงผลลัพธ์ด้วยสี - อ่านง่าย
Maxim Yefremov

27
"ชุดค่าผสมนี้" find ... -execไม่เร็วกว่าgrep --exclude-dirสำหรับฉัน ข้อดีมากมายสำหรับ grep (เร็วกว่าประมาณห้าเท่าด้วยไฟล์ 26k + ที่ถูกกรองออกจาก 38k + บน HDD) เว้นแต่คุณจะแทนที่\;ด้วย+คอมโบ find / exec จากนั้น grep จะเป็น "เพียง" เร็วขึ้นประมาณ 30% ไวยากรณ์ grep ยังเป็นมนุษย์อ่านได้ :)
Kjell Andreassen

เห็นด้วยตั้งแต่นี้ชัดเจน busybox บางอันไม่มีคำสั่ง GREP
hornetbzz

10
โปรดสังเกตว่าคุณสามารถยกเว้นหลายรายการด้วย--exclude-dir={dir1,dir2}
suh

4
ฉันไม่แปลกใจนิดหน่อยที่node_modulesเป็นตัวอย่างที่ยอมรับได้
pdoherty926

983

รุ่นล่าสุดของGNU Grep (> = 2.5.2 ) ให้:

--exclude-dir=dir

ซึ่งไม่รวมไดเรกทอรีที่ตรงกับรูปแบบdirจากการค้นหาไดเรกทอรีแบบเรียกซ้ำ

ดังนั้นคุณสามารถทำได้:

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

สำหรับข้อมูลเพิ่มเติมเล็กน้อยเกี่ยวกับไวยากรณ์และการใช้งานดู

สำหรับ GNU Greps รุ่นเก่าและPOSIX Grepให้ใช้findตามคำแนะนำในคำตอบอื่น ๆ

หรือเพียงแค่ใช้ack( แก้ไข : หรือThe Silver Searcher ) และทำได้ด้วย!


4
@Manocho: ถ้าคุณคิดว่าackดีลอง The Silver Searcher และดูการเพิ่มความเร็ว!
Johnsyweb

30
ไวยากรณ์สำหรับคนใจร้อน: --exclude-dir=dirใช้grepรูปแบบนิพจน์ทั่วไปไม่ใช่ไฟล์ของเชลล์ รูปแบบทำงานบนพา ธ ที่สัมพันธ์กับไดเรกทอรีปัจจุบันของคุณ ดังนั้นรูปแบบการใช้งานไม่ได้--exclude-dir=dir --exclude-dir="/root/dir/*"
tanius

15
หากคุณต้องการยกเว้น dirs หลายรายการจากการค้นหามีตัวเลือกที่ดีกว่าการใช้$ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dirหรือไม่:
Darshan Chaudhary

4
ฉันอาจใช้เวลากับสิ่งนี้มากไปกว่าคนที่มีสติ แต่สำหรับชีวิตของฉันฉันไม่สามารถหาวิธีที่จะแยกไดเรกทอรีย่อยออกจากการค้นหา - ได้grep -r --exclude-dir=public keyword .ผล แต่grep -r --exclude-dir='public/dist' keyword .ไม่ได้ ฉันพยายามเพิ่ม wildex wildcard, การหลบหนีตัวละครอื่น ๆ , แต่ดูเหมือนว่าไม่มีอะไรช่วย
dkobozev

73
ยกเว้นไดเรกทอรีหลายรายการเช่น:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97

78

หากคุณต้องการยกเว้นหลายไดเรกทอรี :

"r" สำหรับการเรียกซ้ำ "l" เพื่อพิมพ์เฉพาะชื่อไฟล์ที่มีการจับคู่และ "i" เพื่อละเว้นความแตกต่างของตัวอักษร:

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

ตัวอย่าง: ฉันต้องการค้นหาไฟล์ที่มีคำว่า 'hello' ฉันต้องการค้นหาในทุกลินุกซ์ไดเรกทอรีของฉันยกเว้น ไดเรกทอรีprocไดเรกทอรีบูตไดเรกทอรีsysและไดเรกทอรีราก :

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

หมายเหตุ: ตัวอย่างด้านบนจำเป็นต้องเป็นรูท

หมายเหตุ 2 (ตาม @skplunkerin): อย่าเพิ่มช่องว่างหลังเครื่องหมายจุลภาค {dir1,dir2,dir3}


5
หมายเหตุ:อย่าเพิ่มช่องว่างหลังเครื่องหมายจุลภาคใน{dir1,dir2,dir3}
skplunkerin

ขอบคุณสะดวกเมื่อ grep'ing ผ่านพื้นที่ทำงาน SVN:grep -Irsn --exclude-dir=.svn 'foo' .
RAM237

1
คุณสามารถระบุ--exclude-dirตัวเลือกได้หลายครั้ง
วอลล์

44

ไวยากรณ์นี้

--exclude-dir={dir1,dir2}

ถูกขยายโดยเชลล์ (เช่น Bash) ไม่ใช่โดยgrepเข้าไปในสิ่งนี้:

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

การอ้างอิงจะป้องกันไม่ให้เชลล์ขยายดังนั้นจึงไม่ทำงาน:

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

รูปแบบที่ใช้กับ--exclude-dirเป็นรูปแบบเดียวกับที่อธิบายไว้ใน man page สำหรับ--excludeตัวเลือก:

--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.

โดยทั่วไปเชลล์จะพยายามขยายรูปแบบดังกล่าวด้วยตนเองดังนั้นเพื่อหลีกเลี่ยงสิ่งนี้คุณควรอ้างอิง:

--exclude-dir='dir?'

คุณสามารถใช้เครื่องมือจัดฟันแบบหยิกและแยกรูปแบบที่ยกมารวมกันดังนี้:

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

รูปแบบสามารถขยายกลุ่มเส้นทางหลายส่วน:

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

topdir/something/elseนี้จะไม่รวมไดเรกทอรีเช่น


13

ใช้สิ่งนี้บ่อย:

grepสามารถใช้ร่วมกับ-r(เรียกซ้ำ), i(ละเว้นกรณี) และ-o(พิมพ์เฉพาะส่วนที่ตรงกันของบรรทัด) หากต้องการยกเว้นการfilesใช้--excludeและเพื่อยกเว้นไดเรกทอรีให้ใช้--exclude-dirและยกเว้นไดเรกทอรีการใช้งาน

เมื่อประกอบเข้าด้วยกันคุณจะพบกับสิ่งที่ชอบ:

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

การอธิบายมันทำให้ฟังดูซับซ้อนกว่าที่เป็นจริง ง่ายต่อการอธิบายด้วยตัวอย่างง่ายๆ

ตัวอย่าง:

สมมติว่าฉันกำลังค้นหาโครงการปัจจุบันสำหรับทุกสถานที่ที่ฉันตั้งค่าสตริงอย่างชัดเจน debuggerในระหว่างเซสชันการดีบักและตอนนี้ต้องการตรวจสอบ / ลบ

ฉันเขียนสคริปต์ชื่อfindDebugger.shและใช้grepเพื่อค้นหาสิ่งที่เกิดขึ้นทั้งหมด อย่างไรก็ตาม:

สำหรับการยกเว้นไฟล์ - ฉันต้องการให้แน่ใจว่า.eslintrcจะถูกละเว้น (อันที่จริงมีกฎเกี่ยวกับการทับหลังdebuggerดังนั้นจึงไม่ควรได้รับการยกเว้น) ในทำนองเดียวกันฉันไม่ต้องการให้สคริปต์ของฉันถูกอ้างอิงในผลลัพธ์ใด ๆ

สำหรับการยกเว้นไดเรกทอรี - ฉันต้องการยกเว้นnode_modulesเนื่องจากมีห้องสมุดจำนวนมากที่อ้างอิงdebuggerและฉันไม่สนใจผลลัพธ์เหล่านั้น นอกจากนี้ฉันแค่อยากจะละเว้น.ideaและ.gitซ่อนเรคคอร์ดเพราะฉันไม่สนใจเกี่ยวกับตำแหน่งการค้นหาเหล่านั้นเช่นกันและต้องการให้ผู้ค้นหาทำการค้นหา

ดังนั้นนี่คือผลลัพธ์ - ฉันสร้างสคริปต์ที่เรียกfindDebugger.shด้วย:

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

ฉันเชื่อว่าตัวเลือก "r" ควรพิมพ์ด้วยตัวพิมพ์ใหญ่ "-R"
hornetbzz

1
น่าสนใจ "r" ได้ผลเสมอสำหรับฉันบนเครื่อง nix และ mac
arcseldon

เมื่อฉันเขียนคำตอบของฉันฉันใช้-R(ฉันจำไม่ได้ว่าทำไมตอนนี้) -rฉันมักจะใช้ แต่กลับกลายเป็นว่ารุ่นพิมพ์ใหญ่ดังนี้ symlinks TIL
Johnsyweb

@Johnsyweb - ขอบคุณ upvoted คำตอบของคุณ - จำไม่ได้ว่าเมื่อมีแนวโน้มในปี 2016 เมื่อฉันเพิ่มนี้ :)
arcseldon

10

คุณสามารถลองสิ่งที่ชอบ grep -R search . | grep -v '^node_modules/.*'


34
ไม่ใช่วิธีแก้ปัญหาที่ดีในบางกรณี ตัวอย่างเช่น: หากไดเรกทอรี 'node_modules' เป็นรายการขนาดใหญ่ที่มีการจับคู่ที่ผิดพลาด (ดังนั้นจึงจำเป็นต้องกรองไดเรกทอรี) ดังนั้น grep แรกจะเสียเวลามากในการค้นหาผ่านไดเรกทอรีย่อยและจากนั้นการกรอง grep ตัวที่สอง ออกการแข่งขัน มันเร็วกว่าในการแยก node_modules ใน grep ตัวแรก
GuruM

2
ฉันไม่สนใจเกี่ยวกับความเชื่องช้าฉันสามารถดูคำสั่งและรู้ว่ามันทำอะไร
Funkodebat

1
เหมือนกันสำหรับความคิดเห็นของคุรุ grep of /varhangs เมื่อมันกระทบกับ/var/runเคสของฉัน ดังนั้นเหตุผลที่ฉันต้องการหลีกเลี่ยงไดเรกทอรีในสถานที่แรก
jww

3
--exclude-dirเป็นทางออกที่ดีที่สุดของปี 2559
Omar Tariq

10

หากคุณกำลัง grepping รหัสในพื้นที่เก็บข้อมูลคอมไพล์และnode_modulesอยู่ในของคุณคุณสามารถใช้.gitignore ค้นหาไฟล์ที่ถูกติดตามในแผนผังการทำงานโดยไม่สนใจทุกสิ่งจากgit grepgit grep.gitignore

git grep "STUFF"

นี่คือเคล็ดลับที่มีประโยชน์มากขอบคุณ
NKM

4

มีประโยชน์มากโดยเฉพาะอย่างยิ่งสำหรับการติดต่อกับNode.jsที่เราต้องการหลีกเลี่ยงการค้นหาใน "node_modules":

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

2

คำสั่งที่ใช้งานง่าย:

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

ด้านบนฉันต้องการข้อความ "creativecommons.org" ในไดเรกทอรีปัจจุบัน "dspace" และยกเว้น dirs {log, assetstore}

เสร็จสิ้น


เรียบร้อยรวมถึงไดเรกทอรีต่าง ๆ ในวงเล็บ
Mijo

2

มีคำตอบที่ถูกต้องมากมายที่นี่ แต่ฉันเพิ่มคำนี้เพื่อเน้นจุดหนึ่งที่ทำให้เกิดความพยายามที่ล้มเหลวก่อนหน้านี้: exclude-dirใช้รูปแบบไม่ใช่เส้นทางไปยังไดเรกทอรี

พูดว่าการค้นหาของคุณคือ:

grep -r myobject

src/other/objects-folderและคุณสังเกตเห็นว่าการส่งออกของคุณจะรกกับผลที่ได้จาก คำสั่งนี้จะไม่ให้ผลลัพธ์ที่ต้องการ:

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

และคุณอาจสงสัยว่าทำไมexclude-dirไม่ทำงาน! หากต้องการยกเว้นผลลัพธ์จากการobjects-folderเพียงทำสิ่งนี้:

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

กล่าวอีกนัยหนึ่งเพียงใช้ชื่อโฟลเดอร์ไม่ใช่พา ธ เห็นได้ชัดเมื่อคุณรู้

จากหน้าคน:

--exclude-dir = GLOB
ข้ามไดเรกทอรีบรรทัดคำสั่งใด ๆ ด้วยคำต่อท้ายชื่อที่ตรงกับรูปแบบ GLOB เมื่อค้นหาแบบวนซ้ำให้ข้ามไดเรกทอรีย่อยที่มีชื่อฐานตรงกับ GLOB ละเว้นเครื่องหมายสแลชต่อท้ายที่ซ้ำซ้อนใน GLOB


2

อันนี้ใช้ได้สำหรับฉัน:

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

5
คำตอบนี้แตกต่างจากสิ่งที่โพสต์แล้ว?
aexl


-1

วิธีที่ง่ายกว่าคือการกรองผลลัพธ์ของคุณโดยใช้ "grep -v"

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


12
นี่คือคำตอบเดียวกันอย่างมีประสิทธิภาพ DipSwitch ที่ให้ไว้ 3 ปีก่อนหน้านี้ มันมีปัญหาเหมือนกันเช่นกัน
jww
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.