ฉันจะค้นหาไฟล์ทั้งหมดที่มีข้อความเฉพาะบน Linux ได้อย่างไร


5257

ฉันพยายามหาวิธีสแกนระบบ Linux ทั้งหมดของฉันสำหรับไฟล์ทั้งหมดที่มีสตริงข้อความที่เฉพาะเจาะจง เพียงชี้แจงฉันกำลังมองหาข้อความภายในไฟล์ไม่ใช่ในชื่อไฟล์

เมื่อฉันมองหาวิธีการทำสิ่งนี้ฉันเจอวิธีแก้ปัญหานี้สองครั้ง:

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

อย่างไรก็ตามมันใช้งานไม่ได้ ดูเหมือนว่าจะแสดงไฟล์ทุกไฟล์ในระบบ

นี่เป็นวิธีที่เหมาะสมในการทำสิ่งนี้หรือไม่? ถ้าไม่ฉันควรทำอย่างไร ความสามารถในการค้นหาสตริงข้อความในไฟล์นี้จะเป็นประโยชน์อย่างยิ่งสำหรับโครงการการเขียนโปรแกรมบางอย่างที่ฉันทำ


21
โปรดจำไว้ว่า grep จะแปลความหมายใด ๆ.ว่าเป็นอักขระตัวแทนเดียวในกลุ่ม คำแนะนำของฉันคือใช้ fgrep หรือ egrep เสมอ
วอลเตอร์ Tross

10
อย่างไรก็ตามคุณเกือบจะอยู่ที่นั่นแล้ว! เพียงแทนที่-Hด้วย-l(และอาจจะgrepด้วยfgrep) หากต้องการยกเว้นไฟล์ที่มีรูปแบบชื่อที่แน่นอนคุณจะต้องใช้findวิธีการขั้นสูงเพิ่มเติม มัน worthwile เรียนรู้ที่จะใช้findแต่ man findเพียงแค่
วอลเตอร์ Tross

6
find … -exec <cmd> +find … -exec <cmd> \;จะง่ายต่อการพิมพ์และเร็วกว่า มันจะทำงานเฉพาะในกรณีที่<cmd>ยอมรับข้อโต้แย้งชื่อไฟล์จำนวนเท่าใดก็ได้ การประหยัดเวลาในการประมวลผลนั้นใหญ่มากหาก<cmd>เริ่มต้นช้าเช่นสคริปต์ Python หรือ Ruby
hagello

ในการค้นหาแบบไม่วนซ้ำในเส้นทางที่กำหนดคำสั่งคือ `grep --include = *. txt -snw" pattern "thepath / *
Stéphane Laurent

@ StéphaneLaurentฉันคิดว่าคุณยุ่งมากเกินไป เพียงแค่พูดgrep "pattern" path/*.txt
fedorqui 'ดังนั้นหยุดทำร้าย'

คำตอบ:


9516

ทำดังต่อไปนี้:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -rหรือ-Rเรียกซ้ำ
  • -n คือหมายเลขบรรทัดและ
  • -w หมายถึงการจับคู่คำทั้งหมด
  • -l (L ตัวพิมพ์เล็ก) สามารถเพิ่มให้เพียงแค่ให้ชื่อไฟล์ของไฟล์ที่ตรงกัน

พร้อมด้วยเหล่านี้--exclude, --include, --exclude-dirธงสามารถนำมาใช้เพื่อการค้นหาที่มีประสิทธิภาพ:

  • สิ่งนี้จะทำการค้นหาไฟล์ที่มีนามสกุล. c หรือ. h เท่านั้น:

    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • วิธีนี้จะยกเว้นการค้นหาไฟล์ทั้งหมดที่ลงท้ายด้วย. o extension:

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • สำหรับไดเรกทอรีเป็นไปได้ที่จะยกเว้นไดเรกทอรีเฉพาะ (IES) ผ่าน--exclude-dirพารามิเตอร์ ตัวอย่างเช่นสิ่งนี้จะยกเว้น dirs dir1 /, dir2 / และพวกเขาทั้งหมดที่ตรงกับ * .dst /:

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

มันใช้งานได้ดีมากสำหรับฉันเพื่อให้บรรลุวัตถุประสงค์เดียวกันเกือบเหมือนคุณ

man grepสำหรับข้อมูลเพิ่มเติมตรวจสอบตัวเลือก


74
ใช้ - ไม่รวม ชอบ "grep -rnw --exclude = *. o 'directory' -e" pattern "
rakib_

98
เป็นที่น่าสังเกตว่า: ดูเหมือนว่าrตัวเลือกจะขี้เกียจ (ลัดเลาะไปตามลำดับแรกลึกกว่าหยุดหลังจากไดเรกทอรีแรก) ในขณะที่Rโลภ (จะข้ามต้นไม้ทั้งหมดอย่างถูกต้อง)
Eliran Malka

5
grep -rnw "String ที่ฉันต้องการ"ทำตามที่ฉันต้องการ ขอบคุณ!
ViliusK

33
หมายเหตุ (โดยเฉพาะสำหรับมือใหม่): เครื่องหมายคำพูดในคำสั่งด้านบนมีความสำคัญ
madD7

69
@Eliran Malka Ren rทั้งสองจะสำรวจไดเรกทอรีอย่างถูกต้อง แต่Rจะติดตามลิงก์สัญลักษณ์
bzeaman

1498

คุณสามารถใช้grep -ilR:

grep -Ril "text-to-find-here" /
  • i ย่อมาจากละเว้นกรณี (ไม่จำเป็นในกรณีของคุณ)
  • R ย่อมาจาก recursive
  • l หมายถึง "แสดงชื่อไฟล์ไม่ใช่ผลลัพธ์"
  • / ย่อมาจากการเริ่มต้นที่รูทเครื่องของคุณ

85
จากประสบการณ์ของฉัน-iทำให้มันช้าลงมากดังนั้นอย่าใช้มันหากไม่จำเป็น ทดสอบใน dir ที่แน่นอนและจากนั้นพูดคุย ควรจะแล้วเสร็จภายในไม่กี่นาที ฉันคิดว่าการแสดงออกปกติจะทำให้ช้าลง แต่ความคิดเห็นของฉันขึ้นอยู่กับการสนับสนุนฉันขอแนะนำให้คุณทดสอบกับtimeด้านหน้าของบรรทัด
fedorqui 'ดังนั้นหยุดการทำร้าย'

4
ใช่/*ย่อมาจากสิ่งนั้น อย่างไรก็ตามฉันเพิ่งทดสอบและสังเกตว่าใช้/งานได้
fedorqui 'ดังนั้นหยุดการทำร้าย'

10
หากคุณไม่ได้ค้นหาด้วย regex คุณสามารถใช้ fgrep แทน grep ในระบบส่วนใหญ่
markle976

8
ใช่ @ markle976 ในความเป็นจริงจากชายคน fgrep is the same as grep -F -> Interpret PATTERN as a list of fixed stringsgrep:
fedorqui 'ดังนั้นหยุดทำอันตราย'

17
คุณสามารถแทนที่ / ด้วยพา ธ ไปยังไดเร็กทอรีgrep -Ril "text-to-find-here" ~/sites/หรือใช้ สำหรับไดเรกทอรีปัจจุบันgrep -Ril "text-to-find-here" .
Black

329

คุณสามารถใช้ack . มันเหมือนกับgrepสำหรับซอร์สโค้ด คุณสามารถสแกนระบบไฟล์ทั้งหมดของคุณด้วย

แค่ทำ:

ack 'text-to-find-here'

ในไดเรกทอรีรากของคุณ

นอกจากนี้คุณยังสามารถใช้นิพจน์ทั่วไประบุประเภทไฟล์ ฯลฯ


UPDATE

ฉันเพิ่งค้นพบThe Silver Searcherซึ่งเป็นเหมือน ack แต่เร็วกว่ามันประมาณ 3-5 เท่าและไม่สนใจรูปแบบจาก.gitignoreไฟล์


57
มีประโยชน์มากง่ายและรวดเร็ว คำเตือน: "ใน Distros ที่ได้รับจาก Debian การรับจะถูกบรรจุเป็น" ack-grep "เนื่องจากมี" ack "อยู่แล้ว" (จากBeyondgrep.com/install ) คุณอาจจะสิ้นสุดการทำงานแปลงรหัสคันจิบน Linuxes ที่ ...
Jose_GD

11
ack หรือ ack-grep มีจุดเด่นที่ดี แต่ค้นหา + grep เมื่อใช้อย่างเหมาะสมดีกว่าในการทำงานมากขึ้น
Sławomir Lenart

14
โปรดทราบว่าripgrepเร็วกว่าอย่างอื่นที่กล่าวถึงที่นี่รวมถึง The Silver Searcher และ grep ol 'ธรรมดา ดูโพสต์บล็อกนี้เพื่อพิสูจน์
Radon Rosborough

194

คุณสามารถใช้ได้:

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

rยืนสำหรับ recursive และเพื่อจะค้นหาในเส้นทางที่ระบุและไดเรกทอรีย่อยของ สิ่งนี้จะบอกคุณถึงชื่อไฟล์รวมทั้งพิมพ์บรรทัดในไฟล์ที่มีสตริงปรากฏ

หรือคำสั่งที่คล้ายกับคำสั่งที่คุณพยายาม (ตัวอย่าง:) เพื่อค้นหาในไฟล์ javascript ทั้งหมด (* .js):

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

นี่จะพิมพ์บรรทัดในไฟล์ที่ข้อความปรากฏขึ้น แต่จะไม่พิมพ์ชื่อไฟล์

นอกเหนือจากคำสั่งนี้เราสามารถเขียนสิ่งนี้ได้เช่นกัน: grep -rn "String to search" / path / to / directory / หรือ / ไฟล์ -r: การค้นหาแบบเรียกซ้ำ n: หมายเลขบรรทัดจะปรากฏขึ้นเพื่อการจับคู่


1
Thanx สำหรับรุ่นค้นหา รุ่น grep ของฉัน (busybox สำหรับ NAS) ไม่ได้มีตัวเลือก -r ฉันต้องการโซลูชันอื่น!
jc

3
ขอบคุณสำหรับรุ่น 'ค้นหา'! เป็นสิ่งสำคัญอย่างยิ่งที่จะสามารถกรองโดย ' .js' หรือ ' .txt' เป็นต้นไม่มีใครต้องการใช้เวลาหลายชั่วโมงเพื่อรอ grep เพื่อค้นหาวิดีโอหลายกิกะไบต์ทั้งหมดจากวันหยุดครอบครัวครั้งล่าสุดแม้ว่าคำสั่งจะเป็น ง่ายต่อการพิมพ์
อันยิ่งใหญ่

grep ดีกว่าเวอร์ชั่นที่ยอมรับเพราะยอมรับไม่ค้นหาคำครึ่งคำ
waza123

114

คุณสามารถใช้สิ่งนี้:

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

12
ง่ายที่สุด verbose, recursive และ case insensitive ยกนิ้ว
Francesco Casula

ถ้าคุณเพิ่ม -A3 ดียิ่งขึ้นด้วย
albanx

73

รายการชื่อไฟล์ที่มีข้อความที่กำหนด

ครั้งแรกของทั้งหมดผมเชื่อว่าคุณได้ใช้แทน-H นอกจากนี้คุณสามารถลองเพิ่มข้อความที่อยู่ภายในคำพูดตามมาด้วย-l{} \

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

ตัวอย่าง

สมมติว่าคุณกำลังค้นหาไฟล์ที่มีข้อความ "Apache License" ในไดเรกทอรีของคุณ มันจะแสดงผลลัพธ์ที่ค่อนข้างคล้ายกับด้านล่าง (ผลลัพธ์จะแตกต่างกันไปตามเนื้อหาไดเรกทอรีของคุณ)

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$ 

ลบความไวของกรณี

แม้ว่าคุณจะไม่ได้ใช้เกี่ยวกับกรณีเช่น "text" vs "TEXT" คุณสามารถใช้-iสวิตช์เพื่อละเว้นกรณีและปัญหา คุณสามารถอ่านรายละเอียดเพิ่มเติมได้ที่นี่

หวังว่านี่จะช่วยคุณได้


2
ซึ่งเป็นสิ่งที่คำสั่งนี้ไม่: จะผ่านเส้นทางทั้งหมดที่พบคำสั่งfind grep -l "text-to-find-here" <file found>"คุณอาจเพิ่มข้อ จำกัด ของชื่อไฟล์เช่นfind / -iname "*.txt"เพื่อค้นหาเฉพาะไฟล์ที่ชื่อลงท้ายด้วย.txt
Men

1
@Auxiliary - รวมเอาท์พุทตัวอย่างเพื่อหลีกเลี่ยงความสับสนสำหรับผู้อ่าน
lkamal

2
@Mene เป็นรัฐที่น่าเศร้าอย่างแท้จริงที่ความคิดเห็นของ Auxiliary มีคะแนนมากกว่าของคุณ ... แม้ว่าความคิดเห็นของพวกเขาจะมาจาก 2014 และของคุณคือ 2017 ที่ความคิดเห็นของพวกเขามี 6 เมื่อมันควรจะมี 0 แน่นอนและของคุณมีเพียงหนึ่ง บางสิ่งที่ฉันอยากจะเชื่อ
Pryftan

@Mene ที่ถูกกล่าวว่า-inameเป็นตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ซึ่งหมายความว่ามันจะหาไฟล์. TXT เช่นเดียวกับ TxT และ TXt และอื่น ๆ
Pryftan

66

grep( GNUหรือBSD )

คุณสามารถใช้grepเครื่องมือเพื่อค้นหาโฟลเดอร์ปัจจุบันซ้ำ ๆ เช่น:

grep -r "class foo" .

หมายเหตุ: -r- ค้นหาไดเรกทอรีย่อยซ้ำ ๆ

คุณยังสามารถใช้ globbing syntax เพื่อค้นหาไฟล์ที่ต้องการเช่น:

grep "class foo" **/*.c

หมายเหตุ: โดยใช้ตัวเลือก globbing ( **) มันจะสแกนไฟล์ทั้งหมดซ้ำด้วยส่วนขยายหรือรูปแบบเฉพาะ หากต้องการเปิดใช้งานไวยากรณ์นี้ให้รัน: shopt -s globstar. นอกจากนี้คุณยังสามารถใช้**/*.*สำหรับไฟล์ทั้งหมด (ไม่รวมที่ซ่อนอยู่และไม่มีส่วนขยาย) หรือรูปแบบอื่น ๆ

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

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

ripgrepอีกวิธีหนึ่งคือใช้

ripgrep

หากคุณกำลังทำงานกับโครงการขนาดใหญ่หรือไฟล์ขนาดใหญ่คุณควรใช้ripgrepแทนเช่น:

rg "class foo" .

ชำระเงินเอกสารขั้นตอนการติดตั้งหรือรหัสที่มาบนหน้าโครงการ GitHub

มันมากเร็วกว่าเครื่องมืออื่น ๆ เช่นGNU / BSD grep , ucg, ag, sift, ack, ptหรือคล้ายกันเพราะมันถูกสร้างขึ้นที่ด้านบนของเครื่องยนต์ regex สนิมของที่ใช้ออโต จำกัด SIMD และการเพิ่มประสิทธิภาพที่แท้จริงในเชิงรุกเพื่อให้สามารถค้นหาได้อย่างรวดเร็ว

มันรองรับรูปแบบการเพิกเฉยที่ระบุใน.gitignoreไฟล์ดังนั้นพา ธ ไฟล์เดียวสามารถจับคู่กับรูปแบบ glob หลายแบบพร้อมกัน


คุณสามารถใช้พารามิเตอร์ทั่วไปเช่น:

  • -i - การค้นหาที่ไม่รู้สึก
  • -I - ละเว้นไฟล์ไบนารี
  • -w - ค้นหาคำทั้งหมด (ตรงข้ามกับการจับคู่คำบางส่วน)
  • -n - แสดงสายการแข่งขันของคุณ
  • -C/ --context(เช่น-C5) - เพิ่มบริบทดังนั้นคุณจะเห็นโค้ดล้อมรอบ
  • --color=auto - ทำเครื่องหมายข้อความที่ตรงกัน
  • -H - แสดงชื่อไฟล์เมื่อพบข้อความ
  • -c- แสดงจำนวนบรรทัดที่ตรงกัน -Hสามารถใช้ร่วมกับ

1
ฉันยังพบว่ามีประโยชน์มากมาย แต่โปรดจำไว้ว่าหากมีไฟล์จำนวนมากจริงๆคุณสามารถได้รับข้อผิดพลาด "รายการอาร์กิวเมนต์ยาวเกินไป" (การโค้งอย่างง่ายนั้นมีแนวโน้มที่จะเกิดข้อผิดพลาดเช่นนี้)
Yoory N.

2
สำหรับการสูดดมระบบไฟล์ทั้งหมด rg จะเจ็บปวดน้อยกว่าเครื่องมืออื่น ๆ เกือบทั้งหมด
lk

55

หากคุณgrepไม่รองรับการค้นหาแบบเรียกซ้ำคุณสามารถใช้ร่วมfindกับxargs:

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

find -execฉันพบนี้ง่ายต่อการจดจำมากกว่ารูปแบบของ

จะส่งออกชื่อไฟล์และเนื้อหาของบรรทัดที่ตรงกันเช่น

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

ตั้งค่าสถานะเพิ่มเติมที่คุณอาจต้องการเพิ่มไปที่grep:

  • -i - การค้นหาแบบตัวเล็กและตัวพิมพ์ใหญ่
  • -l - ส่งออกเฉพาะชื่อไฟล์ที่พบการแข่งขัน
  • -h - ส่งออกเฉพาะสายที่จับคู่ (ไม่ใช่ชื่อไฟล์)

3
ซึ่งเทียบเท่ากับที่grep 'text-to-find-here'ไม่มีชื่อไฟล์หากfindไม่พบสิ่งใด นี่จะเป็นการรอและรอการป้อนข้อมูลจากผู้ใช้! เพิ่มเป็นตัวเลือกให้กับ--no-run-if-empty xargs
hagello

3
การรวมกันของ find และ xargs นี้ไม่ทำงานตามที่ตั้งใจถ้าชื่อไฟล์หรือไดเรกทอรีมีช่องว่าง (ตัวอักษรที่ xargs ตีความเป็นตัวคั่น) find … -exec grep … +ใช้ หากคุณยืนยันในการใช้ร่วมกับหา xargs ใช้และ-print0 -0
hagello

43
grep -insr "pattern" *
  • i: ไม่สนใจความแตกต่างของตัวอักษรทั้งในรูปแบบและไฟล์อินพุต
  • n: นำหน้าแต่ละบรรทัดของเอาต์พุตด้วยหมายเลขบรรทัดที่อ้างอิง 1 ภายในไฟล์อินพุต
  • s: ระงับข้อความแสดงข้อผิดพลาดเกี่ยวกับไฟล์ที่ไม่มีอยู่หรืออ่านไม่ได้
  • r: อ่านไฟล์ทั้งหมดภายใต้แต่ละไดเรกทอรีซ้ำ

3
คุณอธิบายได้ไหมว่าคำตอบของคุณดีขึ้นอย่างไรกับคำตอบอื่น ๆ หรือแตกต่างจากคำตอบเหล่านั้นอย่างเพียงพอ
Amos M. Carpenter

ไม่ซับซ้อนมากนักในการจำจะครอบคลุมทุกรูปแบบ (case-senstivity -> off รวมถึงชื่อไฟล์และหมายเลขบรรทัดและจะทำการค้นหาแบบวนซ้ำ) และใช้ "*" ในท้ายที่สุดจะค้นหาไดเรกทอรีทั้งหมด (ไม่จำเป็นต้องระบุใด ๆ เส้นทางหรือชื่อไดเรกทอรี)
enfinet

ขออภัยฉันควรชัดเจนกว่า: จะดีถ้าคุณสามารถใส่คำอธิบายลงในคำตอบของคุณ ขณะที่มันยืนโดยเฉพาะอย่างยิ่งมีจำนวนมากดังนั้นคำตอบอื่นที่คล้ายคลึงกันอยู่แล้วว่ามันเป็นเรื่องยากที่จะเห็นจากนั้นคำตอบสั้น ๆ สิ่งที่ได้รับประโยชน์จากการพยายามมันมากกว่าคำตอบที่ได้รับการยอมรับหรือหนึ่งในคนที่ upvoted จะเป็น
Amos M. Carpenter

6
@ AmosM.Carpenter สิ่งหนึ่งที่ฉันชอบเกี่ยวกับคำตอบนี้คือการชี้ให้เห็นถึงการระงับการโต้เถียงซึ่งสามารถช่วยกรองสัญญาณรบกวนที่ไม่สำคัญว่าจะได้ผลลัพธ์ที่เราต้องการจริงๆ Grep พิมพ์ข้อผิดพลาดเช่น "ฟังก์ชั่นไม่ได้ใช้งาน", "อาร์กิวเมนต์ไม่ถูกต้อง", "ทรัพยากรไม่พร้อมใช้งาน" ฯลฯ ฯลฯ ในไฟล์ "บางไฟล์"
leetNightshade

@leetNightshade: ฉันสมมติว่าคุณพูดถึงความคิดเห็นของคุณกับฉันเพราะฉันขอคำอธิบายเกี่ยวกับโพสต์ต้นฉบับที่กระจัดกระจาย โปรดดูการปรับปรุงที่ยอดเยี่ยมของ Fabio สำหรับความคิดเห็นก่อนหน้าของฉันเพื่อให้เข้าใจ
Amos M. Carpenter

39

มีเครื่องมือใหม่ที่เรียกว่าThe Silversearcher

sudo apt install silversearcher-ag

มันทำงานอย่างใกล้ชิดกับ Git และ VCS อื่น ๆ ดังนั้นคุณจะไม่ได้อะไรเลยในไฟล์. gitหรือไดเรกทอรีอื่น

คุณสามารถใช้

ag "Search query"

และมันจะทำงานให้คุณ!


35

ฉันจะค้นหาไฟล์ทั้งหมดที่มีข้อความเฉพาะบน Linux ได้อย่างไร ( ... )

ฉันเจอโซลูชันนี้สองครั้ง:

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


หากใช้find like ในตัวอย่างของคุณให้เพิ่ม-s( --no-messages) ไปที่grepและ2>/dev/nullท้ายคำสั่งเพื่อหลีกเลี่ยงการอนุญาตจำนวนมากที่ปฏิเสธข้อความที่ออกโดยgrepและfind:

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

findเป็นเครื่องมือมาตรฐานสำหรับการค้นหาไฟล์ - รวมกับ grep เมื่อค้นหาข้อความที่ต้องการ - บนแพลตฟอร์มที่คล้าย Unix หาคำสั่งมักจะรวมกับ xargsโดยวิธีการ

มีเครื่องมือที่เร็วและง่ายขึ้นสำหรับจุดประสงค์เดียวกัน - ดูด้านล่าง ลองพวกเขาดีกว่าหากพวกเขามีอยู่บนแพลตฟอร์มของคุณแน่นอน:

ทางเลือกที่เร็วและง่ายขึ้น

RipGrep - เครื่องมือค้นหาที่เร็วที่สุดใน:

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

ผู้ค้นหาเงิน :

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

ack :

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

หมายเหตุ: คุณสามารถเพิ่ม2>/dev/nullคำสั่งเหล่านี้ได้เช่นกันเพื่อซ่อนข้อความแสดงข้อผิดพลาดมากมาย


คำเตือน : หากคุณไม่สามารถหลีกเลี่ยงได้จริงๆอย่าค้นหาจาก'/' (ไดเรกทอรีราก)เพื่อหลีกเลี่ยงการค้นหาที่ยาวและไม่มีประสิทธิภาพ! ดังนั้นในตัวอย่างข้างต้นคุณควรแทนที่ ' / ' ด้วยชื่อไดเรกทอรีย่อยเช่น "/ home" ตามที่คุณต้องการค้นหา ...


'find เป็นเครื่องมือมาตรฐานสำหรับการค้นหาไฟล์ที่มีข้อความเฉพาะบนแพลตฟอร์ม Unix'ดูเหมือนว่าค่อนข้างคลุมเครือสำหรับฉัน แม้แต่การเรียกซ้ำgrep findก็ไม่สามารถค้นหาข้อความภายในไฟล์ได้โดยตรง และบางทีเครื่องมือเพิ่มเติมเหล่านั้นมีประโยชน์สำหรับบางคน แต่ตัวจับเวลาเก่าและผู้ที่คุ้นเคยดีเช่นgrepจะไม่ให้พวกเขาตลอดเวลา (ดีแน่นอนฉันจะไม่) ไม่ได้บอกว่ามันไร้ประโยชน์
Pryftan

"... มีข้อความที่เฉพาะเจาะจง ... ": ส่วนนี้ของประโยคไม่ถูกต้อง (เพราะไม่พบว่าตัวเองเกี่ยวข้องกับการค้นหาในส่วนนี้) แก้ไข ขอบคุณ
Bludzee

ดีใจที่ได้รับความช่วยเหลือ! สิ่งเดียวที่จะเห็นได้อย่างรวดเร็วมากก็คือการเปลี่ยนโฟลเดอร์คำเป็นไดเรกทอรีแต่ฉันรู้ว่านั่นเป็นสงครามครูเสดของฉันฉันจะไม่ชนะอย่างสมบูรณ์ อย่ายอมแพ้แม้ว่า ...
Pryftan

ทำไมไม่ "ไดเรกทอรี" แทน "โฟลเดอร์" แต่ทำไม? กรุณาแบ่งปัน "สงครามครูเสด" ของคุณ!
Bludzee

ฉันกำลังบอกว่าใช้ไดเรกทอรีแทน! อ้างถึง: คุณควรแทนที่ '/' ด้วยชื่อโฟลเดอร์ย่อยและมันเป็นสัตว์เลี้ยงที่น่าเบื่อของฉัน .. esp เพราะแม้แต่ Windows ก็เคยเรียกมันว่า 'ไดเรกทอรี' อ่า .. คุณอาจเข้าใจว่า ทำไม? เพราะนั่นคือสิ่งที่เรียกว่า เรียกอีกอย่างว่าที่ระดับระบบไฟล์ และดูด้วยวิธีนี้: มันเคยถูกเรียก (สำหรับ DOS) folหรือไม่? ไม่แน่นอนไม่; มันถูกเรียกdir(และฉันเชื่อว่ามันยังคงเป็น) โฟลเดอร์เป็นสิ่งที่วางแผนไว้ (ฉันเดา) ความเป็นมิตรกับผู้ใช้ แต่ในกรณีนี้มันอาจทำให้ผู้ใช้ 'ขั้นสูง' น้อยลงหรือเปล่า?
Pryftan

29

ลอง:

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

5
นี่เป็นตัวอย่างที่ดีว่าเมื่อใดที่ไม่ควรใช้xargs.. พิจารณาสิ่งนี้ 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นี่จับคู่ไฟล์ผิดและไม่ตรงกับไฟล์ที่ตั้งใจไว้ ใช้อย่างใดอย่างหนึ่งfind .. -print0 | xargs -0 ...แต่นั่นคือการใช้ท่อไร้ประโยชน์หรือดีกว่าfind ... -exec grep ... {} +
shalomb

29

ใช้pwdเพื่อค้นหาจากไดเรกทอรีใด ๆ ที่คุณอยู่ใน recursing ลง

grep -rnw `pwd` -e "pattern"

อัปเดต ทั้งนี้ขึ้นอยู่กับรุ่นของ grep pwdคุณกำลังใช้คุณสามารถละเว้น ในรุ่นที่ใหม่กว่า.ดูเหมือนว่าจะเป็นกรณีเริ่มต้นสำหรับ grep หากไม่ได้รับไดเรกทอรี:

grep -rnw -e "pattern"

หรือ

grep -rnw "pattern"

จะทำในสิ่งเดียวกันกับข้างบน!


3
การใช้pwdไม่จำเป็นเลยเนื่องจากเป็นค่าเริ่มต้น grep -rnw "pattern"พอเพียง
fedorqui 'ดังนั้นหยุดทำอันตราย'

และในความเป็นจริงgrep -rnwและที่คล้ายกันคือสิ่งที่ตอบเหมือนสามปีที่ผ่านมาฉันไม่เห็นว่าคำตอบนี้จะเพิ่มมูลค่า
fedorqui 'ดังนั้นหยุดการทำร้าย'

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

คุณหมายความว่าอย่างไรกับ "รูปแบบเริ่มต้น" คำตอบที่ได้รับการยอมรับประกอบด้วยgrep -rnw '/path/to/somewhere/' -e "pattern"สิ่งที่คุณมีอยู่ที่นี่ 5 คะแนนโหวตหลังจากการเยี่ยมชม 2.3M ไม่ได้หมายความว่ามาก
fedorqui 'ดังนั้นหยุดการทำร้าย'

ฉันเห็นด้วย :-) สิ่งที่ฉันหายไปในคำตอบเดิมคือกรณีการใช้งานที่คุณไม่ต้องให้เส้นทางเลยหรือเพื่อค้นหาไดเรกทอรีปัจจุบันซ้ำซึ่งไม่สะท้อนในคำตอบที่ยอมรับ ดังนั้นมันจึงเป็นประสบการณ์การเรียนรู้ที่ดีเกี่ยวกับ grep เพื่อขุดลึกลงไปอีกเล็กน้อย
mahatmanich

19

grep สามารถใช้ได้แม้ว่าเราจะไม่ได้มองหาสตริง

เพียงแค่วิ่ง

grep -RIl "" .

จะพิมพ์พา ธ ไปยังไฟล์ข้อความทั้งหมดเช่นที่มีอักขระที่พิมพ์ได้เท่านั้น


2
ฉันไม่เห็นว่าสิ่งนี้ดีกว่าการใช้เพียงlsหรือfind(สำหรับการเรียกซ้ำ)
fedorqui 'ดังนั้นหยุดการทำร้าย'

17

นี่คือรายการคำสั่งหลายรายการที่สามารถใช้เพื่อค้นหาไฟล์

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
สิ่งนี้เพิ่มไปยังคำตอบที่มีอยู่?
fedorqui 'ดังนั้นหยุดทำอันตราย'

@fedorqui egrepเทียบเท่าgrep -Eและหมายความว่า--extended-regexpคุณสามารถหารายละเอียดได้ที่นี่unix.stackexchange.com/a/17951/196072
omerhakanbilici

17

Silver Searcher เป็นเครื่องมือที่ยอดเยี่ยม แต่ ripgrep อาจดีกว่า

ใช้งานได้กับ Linux, Mac และ Windows และเขียนขึ้นในHacker Newsเมื่อสองสามเดือนที่ผ่านมา (มีลิงก์ไปยังบล็อกของ Andrew Gallant ซึ่งมีลิงค์ GitHub):

Ripgrep - เครื่องมือค้นหาบรรทัดคำสั่งใหม่


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

คำอธิบายจากความคิดเห็น

find คือคำสั่งที่ให้คุณค้นหาไฟล์และวัตถุอื่น ๆ เช่นไดเรกทอรีและลิงก์ในไดเรกทอรีย่อยของเส้นทางที่กำหนด หากคุณไม่ได้ระบุมาสก์ที่ชื่อไฟล์ควรตรงกับมันจะระบุออบเจ็กต์ไดเรกทอรีทั้งหมด

-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

ลอง:

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

ซึ่งจะค้นหาระบบไฟล์ทั้งหมดเนื่องจาก/เป็นโฟลเดอร์รูท

สำหรับการใช้งานโฮมโฟลเดอร์:

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

สำหรับการใช้โฟลเดอร์ปัจจุบัน:

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

บางทีรายละเอียดเกี่ยวกับความแตกต่างของโฟลเดอร์นั้นชัดเจนสำหรับหลาย ๆ คน แต่ก็มีประโยชน์สำหรับมือใหม่ +1
nilon

1
สิ่งนี้เพิ่มไปยังคำตอบที่มีอยู่?
fedorqui 'ดังนั้นหยุดทำอันตราย'

เรียกมันว่าสงครามครูเสดของฉัน แต่คำว่า 'ไดเรกทอรี' นี่ไม่ใช่ Windows (ซึ่งเคยใช้ 'ไดเรกทอรี' อยู่แล้ว - ก่อน 9x) กรุณาหยุดพูด 'โฟลเดอร์' สำหรับคำสั่งสุดท้ายของคุณคุณไม่จำเป็นต้องมี '/' เพียงแค่ FYI
Pryftan

15

หวังว่านี่จะช่วยได้ ...

การขยายgrepบิตเพื่อให้ข้อมูลเพิ่มเติมในเอาต์พุตตัวอย่างเช่นเพื่อรับหมายเลขบรรทัดในไฟล์ที่สามารถทำข้อความได้ดังนี้:

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

และหากคุณมีความคิดว่าประเภทไฟล์คืออะไรคุณสามารถ จำกัด การค้นหาของคุณให้แคบลงโดยระบุนามสกุลไฟล์ที่จะค้นหาในกรณี.pasหรือ.dfmไฟล์นี้:

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

คำอธิบายสั้น ๆ ของตัวเลือก:

  1. .ในการfindระบุจากไดเรกทอรีปัจจุบัน
  2. -name" *.*": สำหรับไฟล์ทั้งหมด (-name " *.pas" -o -name " *.dfm"): เฉพาะ*.pasหรือ*.dfmไฟล์หรือระบุด้วย-o
  3. -type f ระบุว่าคุณกำลังมองหาไฟล์
  4. -print0และ--nullอีกด้านหนึ่งของ|(ท่อ) เป็นสิ่งสำคัญที่ส่งผ่านชื่อไฟล์จากfindไปยังที่grepฝังอยู่ในการxargsอนุญาตให้ผ่านชื่อไฟล์ที่มีช่องว่างในชื่อไฟล์ที่ช่วยให้ grep เพื่อรักษาเส้นทางและชื่อไฟล์เป็นหนึ่งสาย และไม่ทำลายมันในแต่ละพื้นที่

-name '*.*'ไม่ใช่สิ่งที่คุณพูด มันจะไม่รับในไฟล์ที่เรียกว่า 'file' เพราะรูปแบบไม่เท่ากับ (ไม่มี. text); *จะอย่างไรก็ตาม (กัน. ไฟล์กัน) แต่มีสิ่งอื่น: ถ้าคุณต้องการไฟล์ทั้งหมดทำไมต้องระบุชื่อไฟล์ตั้งแต่แรก? ไม่มีความคิดเห็นอื่น - ยกเว้นว่าเป็นการดีที่รู้ว่ายังมีคนที่ไม่ได้ใช้ 'โฟลเดอร์' คำศัพท์ MS (ซึ่งจริงๆแล้วหลังจากบอกว่าพอฉันจะไม่เพิ่ม แต่ฉันอยากจะชี้ให้เห็นคำสั่งที่ไม่ถูกต้องเล็กน้อยที่คุณทำ ด้วยชื่อไฟล์ - รวมถึงความซ้ำซ้อน / ไร้ประโยชน์ในกรณีของ 'ทั้งหมด')
Pryftan

15

เรียบง่ายfindสามารถทำงานได้สะดวก นามแฝงใน~/.bashrcไฟล์ของคุณ:

alias ffind find / -type f | xargs grep

เริ่มเทอร์มินัลใหม่และปัญหา:

ffind 'text-to-find-here'

14

ฉันเขียนสคริปต์ Pythonซึ่งทำสิ่งที่คล้ายกัน นี่คือวิธีการใช้สคริปต์นี้

./sniff.py path pattern_to_search [file_pattern]

อาร์กิวเมนต์แรกpathคือไดเรกทอรีที่เราจะค้นหาแบบวนซ้ำ อาร์กิวเมนต์ที่สองpattern_to_searchเป็นนิพจน์ทั่วไปที่เราต้องการค้นหาในไฟล์ เราใช้รูปแบบการแสดงออกปกติที่กำหนดไว้ในห้องสมุดหลาม reในสคริปต์.นี้ยังตรงกับบรรทัดใหม่

อาร์กิวเมนต์ที่สามfile_patternเป็นทางเลือก นี่เป็นอีกนิพจน์ปกติที่ใช้กับชื่อไฟล์ เฉพาะไฟล์ที่ตรงกับนิพจน์ทั่วไปนี้เท่านั้นที่จะได้รับการพิจารณา

ตัวอย่างเช่นถ้าฉันต้องการค้นหาไฟล์ Python ด้วยนามสกุลpyที่มีPool(คำAdaptorต่อท้ายฉันจะทำสิ่งต่อไปนี้

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

และ voila มันสร้างเส้นทางของไฟล์ที่ตรงกันและหมายเลขบรรทัดที่พบการแข่งขัน หากพบการแข่งขันมากกว่าหนึ่งรายการหมายเลขบรรทัดแต่ละรายการจะถูกต่อท้ายชื่อไฟล์


14

หากคุณต้องการใช้อย่างเคร่งครัดให้findใช้find + grep:

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

ขั้นตอน

1. ใช้findเพื่อค้นหาไฟล์
2. จากนั้นเรียกใช้งานไฟล์grepทั้งหมด

วิธีนี้จะช่วยให้คุณfindสามารถค้นหาไฟล์ได้

  • ใช้-name Patternหากคุณต้องการgrepไฟล์บางไฟล์เท่านั้น:

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

คุณสามารถเล่นกับมันและใช้ตัวเลือกต่าง ๆfindเพื่อปรับปรุงหรือ จำกัด การค้นหาไฟล์ของคุณ


อะไรคือความแตกต่าง? มันจะทำงานกับช่องว่างในเส้นทางไฟล์หรือไม่
Peter Mortensen

13

ใช้:

grep -c Your_Pattern *

สิ่งนี้จะรายงานจำนวนสำเนาของรูปแบบของคุณที่มีในแต่ละไฟล์ในไดเรกทอรีปัจจุบัน


13

grepเป็นเพื่อนที่ดีของคุณเพื่อให้บรรลุนี้

grep -r <text_fo_find> <directory>

หากคุณไม่สนใจเกี่ยวกับตัวพิมพ์เล็กและใหญ่ของข้อความให้ใช้:

grep -ir <text_to_find> <directory>

ในกรณีของฉันดูเหมือนว่าจะค้นหาได้ทุกที่แม้ว่าฉันจะระบุไดเรกทอรี
Pathros

@Pathros อาจจะเปิดใช้งานการเรียกซ้ำและไดเรกทอรีที่คุณระบุ อีกวิธีหนึ่งที่การเรียกซ้ำจะเปลี่ยนสิ่งต่าง ๆ ในลักษณะนั้น
Pryftan

@Pathros โอ้และถ้ามีข้อความใด ๆ-ในสตริงการค้นหาคุณจะต้องส่งผ่าน--ไปยัง grep ก่อน ที่อาจทำให้เกิดผลข้างเคียงที่น่าสนใจเป็นอย่างอื่น!
Pryftan

13

ฉันรู้สึกทึ่งกับความเรียบง่ายของgrep ที่ทำด้วย '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'

ใช้ '-r' โดยไม่มี 'l' เพื่อดูชื่อไฟล์ตามด้วยข้อความที่พบรูปแบบ !

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

มันใช้งานได้สมบูรณ์แบบ ...


สิ่งนี้ยังทำงานในGit Bash (Windows)
Peter Mortensen

แต่มันหมายถึงทุกไฟล์ต้องค้นหา (ไม่มีตัวกรองชื่อไฟล์หรือระดับนามสกุลไฟล์เช่น.txt) หรือมีวิธีการทำเช่นนั้น?
Peter Mortensen

12

ในการค้นหาสตริงและเอาต์พุตเพียงบรรทัดนั้นด้วยสตริงการค้นหา:

for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done

เช่น:

for i in $(find /usr/share/applications -type f); \
do grep -i "web browser" "$i"; done

ในการแสดงชื่อไฟล์ที่มีสตริงการค้นหา:

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;

เช่น:

for i in $(find /usr/share/applications -type f); \
do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
fi; done;

1
ฉันเห็นข้อเสียเพียงอย่างเดียวเมื่อเทียบกับการใช้find … -exec grep 'str' {} \;(ถ้าคุณต้องใช้findเลย)
phk

1
สิ่งนี้จะพังอย่างน่ากลัวหากไฟล์ใด ๆ ที่พบโดยการfindเว้นวรรคที่มี .. คุณสามารถท้ายgreppingไฟล์ผิดและ / หรือไฟล์ที่ถูกต้องหายไปทั้งหมด เพียงแค่ใช้find ... -exec grep ...ถ้าคุณมีความจำเป็นต้องใช้find.. แต่ในกรณีนี้ก็grep -r ...เพียงพอแล้ว
shalomb

1
จุดประสงค์ของการใช้ลูปในผลลัพธ์การค้นหาเพื่อ grep คืออะไร สิ่งนี้มีความซับซ้อนโดยไม่จำเป็น
fedorqui 'ดังนั้นหยุดทำอันตราย'

12

มีackเครื่องมือที่จะทำสิ่งที่คุณกำลังมองหา

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

ack -i search_string folder_path/*

คุณอาจไม่สนใจ-iการค้นหาที่ตรงตามตัวพิมพ์ใหญ่ - เล็ก


2
นี่คือการเพิ่มคำตอบที่มีอยู่? สิ่งนี้แนะนำมานานกว่าสามปีที่แล้ว
fedorqui 'ดังนั้นหยุดทำอันตราย'

1
@fedorqui 1) ไม่มีท่อ! 2) ใช้นิพจน์ทั่วไป 3) รับหมายเลขบรรทัดชื่อไฟล์ที่มีพา ธ สัมพัทธ์ข้อความที่ไฮไลต์และมีประโยชน์สำหรับการแก้ไขหลังจากการค้นหาเช่น "vim + lineno path / file.cpp" จะทำให้คุณอยู่ในบรรทัดที่ไม่สนใจ ดูผลลัพธ์ของคำสั่ง "ack include \ | hpp" ที่ค้นหาคำสำคัญ "include" หรือ "hpp" ภายใต้โฟลเดอร์การค้นหาและโฟลเดอร์ย่อยของฉัน ฉันหวังว่าจุดชัดเจน นี่คือตัวอย่างเอาต์พุต (ไม่สามารถแสดงไฮไลต์คำหลักด้วยข้อความแบบง่าย) process / child.hpp 11: boost / process / child.hpp process / all.hpp 21: #include <boost / process / execute.hpp>
Pal

12

คำตอบก่อนหน้านี้ทั้งหมดแนะนำ grep และค้นหา แต่มีวิธีอื่น: ใช้ผู้บัญชาการเที่ยงคืน

มันเป็นยูทิลิตี้ฟรี (อายุ 30 ปีพิสูจน์ตามเวลา) ซึ่งเป็นภาพโดยไม่ต้องเป็น GUI มันมีฟังก์ชั่นมากมายและการค้นหาไฟล์เป็นเพียงหนึ่งในนั้น


เรนเจอร์จะอยู่ในความคิดเดียวกัน
nilon

11

คำสั่งด้านล่างจะทำงานได้ดีสำหรับวิธีการนี้:

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

2
สิ่งที่เป็นจุดของการใช้findแล้วgrep -r? มันมีความหมายเหมือนกันดังนั้นนี่จึงซ้ำซ้อน
fedorqui 'ดังนั้นหยุดทำอันตราย'

โอ๋ !! แก้ไขแล้วจริง ๆ แล้ว find ใช้สำหรับการรัน grep ในไฟล์ที่ถูกกรองและไม่ใช่ทั้งหมดขอบคุณ
Pradeep Goswami

2
ยังคงนี้ไม่ได้ทำให้รู้สึกใด ๆ findคุณสามารถกรองด้วย
fedorqui 'ดังนั้นหยุดทำอันตราย'

11

หลีกเลี่ยงความยุ่งยากและติดตั้ง ack-grep มันกำจัดปัญหาสิทธิ์และใบเสนอราคาจำนวนมาก

apt-get install ack-grep

จากนั้นไปที่ไดเรกทอรีที่คุณต้องการค้นหาและเรียกใช้คำสั่งด้านล่าง

cd /
ack-grep "find my keyword"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.