วิธีใช้คำสั่ง“ grep” เพื่อค้นหาข้อความรวมถึงไดเรกทอรีย่อย


373

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


grep -RIn <yor pattern> * จะค้นหาจากไดเรกทอรีปัจจุบันในไฟล์ข้อความทั้งหมด ไม่แน่ใจว่าจะทำการค้นหาของฉันซ้ำในรูปแบบไฟล์เช่น * .C โดยใช้ grep เท่านั้น

1
สัญลักษณ์แทนด้วย--include="*.C"ตัวเลือก @ user311346 ขอบคุณ @Lekensteyn
Bob Stein

ใช้ชุดการค้นหาและ grep เพื่อค้นหาไฟล์ซ้ำสำหรับสตริงในไดเรกทอรีปัจจุบันและไดเรกทอรีย่อยทั้งหมด ตรวจสอบwilddiary.com/find-files-containing-my-text
Drona

คำตอบ:


487

มันจะดีกว่าที่จะใช้

grep -rl "string" /path

ที่ไหน

  • -r(หรือ--recursive) ตัวเลือกที่ใช้ในการสำรวจยังไดเรกทอรีย่อยทั้งหมดของ/pathในขณะที่
  • -l--files-with-matchesตัวเลือก(หรือ) ใช้เพื่อพิมพ์ชื่อไฟล์ของไฟล์ที่ตรงกันเท่านั้นและไม่ใช่บรรทัดที่ตรงกัน (ซึ่งสามารถปรับปรุงความเร็วได้เช่นกันเนื่องจากgrepหยุดอ่านไฟล์ในการจับคู่ครั้งแรกด้วยตัวเลือกนี้)

13
จริง ๆ แล้วถ้า "สตริง" เป็นรูปแบบข้อความที่จะค้นหามันจะดีกว่าที่จะใช้ฟังก์ชั่นนั้นมิฉะนั้นใครบางคนสามารถประสบปัญหาเมื่อสตริงมีจุดหรืออักขระพิเศษที่มีความหมายในการแสดงออกปกติและไม่เพียงแค่จุดที่ควรจะพบว่าเป็นสตริง , อย่างที่เป็น. จากนั้นฉันจะใช้-rlFสวิตช์-Fสำหรับ "สตริงคงที่" (และไม่ใช่ regexp - เช่น) แน่นอนถ้างานนั้นใช้ regexps แล้วก็ขอโทษด้วย แน่นอนว่าทฤษฎีเดียวกันโดยไม่มี -r เช่นกันฉันมักจะเห็นว่าคนสันนิษฐานว่า grep ค้นหา "ข้อความ" และอาจทำให้เกิดปัญหาที่คนพิเศษซึ่งหมายถึงบางสิ่งบางอย่างเป็น regexp
LGB

4
นอกจากนี้ยังมีการ-iตั้งค่าสถานะซึ่งไม่สนใจขนาดตัวพิมพ์
Marco Ceppi

3
ฉันจะแสดง--recursiveตัวเลือกเท่านั้นมีตัวเลือกมากมายและสถานการณ์การใช้งานที่คนสามารถพูดคุยได้ ผมเริ่มจากคำตอบที่ @dmityugov findรับการยอมรับและมีการปรับเปลี่ยนการทำงานโดยไม่มี
enzotib

1
@NN: เรียบร้อยแล้ว :-)
enzotib

3
@ScottBiggs: พร้อมตัวเลือก--include '*.h'
enzotib

167

หากคุณกำลังมองหาการจับคู่บรรทัดในไฟล์คำสั่งโปรดของฉันคือ:

grep -Hrn 'search term' path/to/files
  • -H ทำให้ชื่อไฟล์ที่จะพิมพ์ (โดยนัยเมื่อค้นหาหลายไฟล์)
  • -r การค้นหาแบบเรียกซ้ำ
  • -n ทำให้หมายเลขบรรทัดถูกพิมพ์

path/to/filesสามารถ.ค้นหาในไดเรกทอรีปัจจุบัน

ตัวเลือกเพิ่มเติมที่ฉันพบว่ามีประโยชน์มาก:

  • -Iละเว้นไฟล์ไบนารี (ส่วนประกอบ: -aถือว่าไฟล์ทั้งหมดเป็นข้อความ)
  • -Fถือว่าsearch termเป็นตัวอักษรไม่ใช่นิพจน์ปกติ
  • -i ทำการค้นหาแบบตรงตามตัวพิมพ์ใหญ่ - เล็ก
  • --color=alwayslessเพื่อบังคับให้สีแม้ในขณะที่ท่อผ่าน ในการสร้างlessสีสนับสนุนคุณต้องใช้-rตัวเลือก:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dirมีประโยชน์สำหรับการยกเว้นไดเรกทอรีเช่นและ.svn.git

ตัวอย่างผลลัพธ์


13
-Hในโฟลเดอร์ซ้ำซ้อนหากมีมากกว่าหนึ่งไฟล์ตามที่เป็นไปได้ อันที่จริงแล้วหน้าคนพูด-H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search.
enzotib

ฉันไม่ทราบว่ามันทำงานได้เหมือนที่คาดไว้เสมอ มันเป็นคำสั่งเริ่มต้นของฉันเมื่อค้นหาไฟล์
Lekensteyn

1
มีวิธีพิจารณาเฉพาะไฟล์ที่มี, a, พูด, .a extention (และเพื่อรวมเข้ากับ -r) หรือไม่?
user2413

6
@ user2413 ลอง--include '*.*'
Lekensteyn

1
@alper Trygrep --exclude='*~' ...
Lekensteyn

24

ฉันเชื่อว่าคุณสามารถใช้สิ่งนี้:

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

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

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

  • -type f ระบุว่าควรประมวลผลไฟล์เท่านั้นไม่ใช่ไดเรกทอรีเป็นต้น
  • -exec grepระบุว่าสำหรับทุก ๆ ไฟล์ที่พบควรรันคำสั่ง grep ส่งชื่อไฟล์เป็นอาร์กิวเมนต์ไปยังโดยแทนที่{}ด้วยชื่อไฟล์

3
สำหรับผู้ที่ไม่ทราบเท่านั้นเพิ่มการ-name '*.py'จำกัด การแข่งขันให้กับไฟล์ที่ลงท้ายด้วย '.py'
Daniel F

ฉันชอบที่นี่ครอบคลุมลูกค้าที่ไม่ได้ใช้ -R ในคำสั่ง grep ของพวกเขา
Aviose

หากคุณต้องการพิมพ์บรรทัดและชื่อไฟล์ที่ตรงกันให้ exec ชอบ:... -exec bash -c 'grep -r "mystring" {} && echo {}' \;
Donn Lee

อะไรคือสิ่งที่สัมพันธ์กับการใช้ grep โดยตรง
โจนาธาน

19

คำสั่งเริ่มต้นของฉันคือ

grep -Rin string *

ฉันใช้ศาลากลาง 'R' เพราะlsใช้เพื่อเรียกซ้ำ เนื่องจาก grep ยอมรับทั้งสองจึงไม่มีเหตุผลที่จะไม่ใช้มัน

แก้ไข: ต่อการประชุม HVNS ดูเหมือนว่า-Rจะเป็นไปตามsymlink โดยที่-rไม่เป็นเช่นนั้น


1
หากต้องการค้นหาในไฟล์ที่ซ่อนอยู่ให้เรียกใช้shopt -s dotglob(จำไว้-sว่า "set") ระวังเมื่อทำการลบไฟล์แล้ว หากคุณเปิดใช้งาน dotglob ให้rm -r *ลบทุกอย่างใน dir ปัจจุบัน แต่ยังรวมถึงไดเรกทอรีด้านบนเพราะ..ตรงกัน หากต้องการปิดใช้งาน dotglob ให้ใช้shopt -u dotglob("unset") การเปลี่ยนแปลงเป็นการชั่วคราวแม้ว่าจะใช้กับเชลล์ปัจจุบันเท่านั้น
Lekensteyn

ฉันลืมเรื่องนี้ มีวิธีการตั้งค่าสำหรับหนึ่งบรรทัดหรือไม่? บางอย่างที่shopt -s dotglob & <grep cmd> & shopt -y dotglobสะดวกกว่าเท่านั้น? วิธีนี้เราไม่ต้องกังวลเกี่ยวกับการรีเซ็ต
user606723

นอกจากนี้อาจใช้งานได้ง่ายกว่าgrep -Rin string .ในกรณีส่วนใหญ่ ฉันใช้ * เพราะมันดูเป็นธรรมชาติมากขึ้น
user606723

1
หากคุณทำ grep ซ้ำคุณก็สามารถเริ่มจาก "." แทน "*". ไม่จำเป็นต้องใช้ dotglob
MichałŠrajer

1
ออกเสียงลงคะแนนสิ่งนี้สิ่งหนึ่งที่ไม่ได้กล่าวถึงใน manpage คือRจะเป็นไปตามลิงก์สัญลักษณ์rไม่ได้
HVNSweeting

12

หากคุณยินดีลองสิ่งใหม่ ๆ ลองackถ่ายภาพ คำสั่งเพื่อค้นหาไดเร็กทอรีปัจจุบันซ้ำ ๆstringคือ:

ack string

การติดตั้งค่อนข้างง่าย:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(ระบุว่าคุณมีไดเรกทอรีอยู่แล้ว~/binและควรเป็นของคุณPATH)


2
หรือเพียงติดตั้ง apt-get ack-grep (และเพิ่ม alias ack = ack-grep ใน. bashrc ของคุณ)
markijbema

พารามิเตอร์สุดท้ายของchmodคำสั่งทำอะไร พวกเขาเฉพาะสำหรับchmodหรือพวกเขาเกี่ยวข้องกับทุบตี ( !#:3ส่วน)?
Elliott Darfink

@ElliottDarfink นั่นคือใช้ทุบตีของประวัติ - !เป็นdesignator เหตุการณ์ พวกมันค่อนข้างทรงพลังที่จะหลีกเลี่ยงการทำซ้ำ !#:3อ้างอิงโทเค็นที่สามของบรรทัดคำสั่งจนถึงขณะนี้คือ~/bin/ackในกรณีนี้
Konrad Rudolph

4

คำสั่ง rgrep มีไว้สำหรับความต้องการเช่นนั้น

หากไม่สามารถใช้ได้คุณจะได้รับเช่นนี้

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

คุณสามารถตั้งค่าตัวเลือก grep เริ่มต้นได้โดยตรงตามที่อธิบายไว้ข้างต้น

ฉันใช้คน

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

หัวข้อที่เกี่ยวข้อง: วิธีใช้ rgrep กับสีเสมอ


rgrep มีให้ในแพ็คเกจ grep ซึ่งติดตั้งโดยค่าเริ่มต้นใน Ubuntu
karel

2

อัปเดต 2:

บรรทัดคำสั่งนี้ใช้findและgrepแก้ไขปัญหา:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> สำหรับการแสดงผลสี:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

ตัวอย่าง:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

ตัวอย่างการทำงานในภาพรวมด้านล่าง: snap1


อัปเดต 1:

คุณสามารถลองรหัสต่อไปนี้; เป็นฟังก์ชั่นในของคุณ.bashrcหรือ.bash_aliasesหรือในสคริปต์:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

การใช้งาน: wherein /path/to/search/in/ searchkeyword

ตัวอย่าง:

$ wherein ~/Documents/ "hello world"

(หมายเหตุ: ตามที่แนะนำในความคิดเห็นด้านล่างโดย @enzotib สิ่งนี้จะไม่ทำงานกับไฟล์ / ไดเรกทอรีรวมถึงช่องว่างในชื่อ)


โพสต์ต้นฉบับ

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

$ 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;

ล้มเหลวในชื่อไฟล์ที่มีช่องว่าง ความล้มเหลวถูกซ่อนอยู่โดยข้อเท็จจริงที่ว่า stderr ไม่ปรากฏขึ้น
enzotib

@enzotib ขอบคุณสำหรับการชี้ให้เห็นว่า .. ยังไม่ได้รับการแก้ไขสำหรับฟังก์ชั่นที่ระบุ .. ฉันได้เพิ่มอีกหนึ่งซับแม้ว่า ..
แม่นยำ

ตอนนี้คำตอบนั้นคล้ายกับของ @dmityugov
enzotib

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

2

grep( GNUหรือBSD )

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

grep -r "pattern" .

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

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

grep "class foo" **/*.c

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

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

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

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

ripgrep

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

rg "pattern" .

ชำระเงินเอกสารขั้นตอนการติดตั้งหรือรหัสที่มาบนหน้าโครงการ 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

ฉันทำได้โดยใช้ xargs คำสั่ง underrated มาก

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

find ./ ให้รายการที่ซ้ำของไฟล์ทั้งหมดในโฟลเดอร์ปัจจุบันจากนั้นให้คุณไพพ์ไปที่ xargs ที่เรียกใช้คำสั่ง grep ในแต่ละไฟล์


4
การใช้xargsโดยไม่ใช้ -print0ตัวเลือกfindและ-0ตัวเลือกที่xargsจะเลิกใช้งานจะล้มเหลวในชื่อไฟล์ที่มีช่องว่าง
enzotib

@enzotib ฉันได้แก้ไขคำตอบตามที่คุณแนะนำ - โปรดตรวจสอบและหากต้องการแก้ไขและแก้ไขฉันยินดีที่จะแก้ไขอีกครั้งโดยคุณ ขอบคุณ
αғsнιη

1
@KasiyA: มันก็โอเคเอาออก downvote ของฉัน
enzotib

0

ฉันรู้ว่ามีคำตอบมากมายที่นี่ แต่เป็นอีกทางเลือกถ้าคุณต้องการเพิ่มข้อ จำกัด อื่น ๆ เมื่อค้นหาไฟล์:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

สิ่งนี้ใช้งานได้เพราะgrepจะส่งคืน 0 หากพบผลลัพธ์หรือ 1 เป็นอย่างอื่น ตัวอย่างเช่นคุณสามารถค้นหาไฟล์ขนาดใหญ่ 1 MB และมีบางสิ่ง:

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

สำหรับความต้องการหลายประการคุณอาจต้องการใช้การตั้งค่าเครื่องมือเพิ่มประสิทธิภาพ-Oที่มีอยู่ใน grep GNU


0

สคริปต์ (ค้นหาในรหัส) เพื่อค้นหาใน C, รหัส CPP:

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

ใช้:

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