กำลังค้นหาซับสตริงในไฟล์ข้ามไดเรกทอรีย่อยด้วยคำสั่งในตัวเดียวหรือไม่


10

ใน Windows ถ้าฉันต้องการค้นหาสตริงในไฟล์ทั้งหมดในไดเรกทอรีย่อยทั้งหมดฉันจะทำสิ่งที่ต้องการ

findstr /C:"the string" /S *.h

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

คำตอบ:


19

grep ของ GNU อนุญาตให้ค้นหาซ้ำผ่านไดเรกทอรีย่อย:

grep -r --include='*.h' 'the string' .

ฉันลองใช้บรรทัดคำสั่งที่แน่นอนใน Ubuntu แต่ได้รับ "grep: ตัวเลือกที่ไม่ถูกต้อง - 'M'" ถึงแม้ว่าฉันจะไม่เห็น 'M' ใดก็ได้ ... งงงวย
Guido Domenici

@Guido ทำงานได้ดีที่นี่
phunehehe

ในการแก้ไขที่ แนะนำTomasGแนะนำให้เปลี่ยนค่าล่าสุด*เป็น'*': "จำเป็นต้องมีการอ้างถึงสัญลักษณ์ตัวแทนล่าสุดเพื่อหลีกเลี่ยงข้อผิดพลาดเมื่อชื่อไฟล์บางชื่อขึ้นต้นด้วย -"
Michael Mrozek

ในเหตุการณ์แปลก ๆ มันก็ใช้ได้กับฉันเหมือนกันกับคำตอบเดิม ขอบคุณ!
Guido Domenici

1
@Guido: ปัญหาของคุณอาจเกิดจากไฟล์ในไดเรกทอรีปัจจุบันที่เรียกว่า-MsomethingหรือการGREP_OPTIONSตั้งค่า
Gilles 'หยุดชั่วร้าย'

2

grep -r searchpattern /path/to/start/in

/path/to/start/in/สามารถอยู่ที่.ไดเรกทอรีปัจจุบันได้เพียง " "


1

ไม่ find -name \*.h -print0 | xargs -0 grep -l 'the regex'ได้วิเศษเท่าที่จะได้รับ


grep GNU มีเคสทั่วไปที่มีอยู่ในตัวพร้อม-rตัวเลือก ไม่จำเป็นต้องมีปืนใหญ่
Gilles 'หยุดชั่วร้าย'

3
xargsเพิ่มเสียงรบกวนเพียง ใช้find -name \*.h -execdir grep -l 'the regex {} +
ผู้ใช้ที่ไม่รู้จัก

0

มีคำสั่งในตัวเดียวที่ทำงานผ่านเวทมนตร์นี้ ... ?

เพื่อที่จะอวดความรู้ไม่มีคุณไม่สามารถสันนิษฐานได้ว่าคำสั่งดังกล่าวที่มีอยู่

มีการใช้งานที่แตกต่างกันของ Unix และแต่ละอันมีนิสัยแตกต่างกัน POSIX, ตัวหารร่วม (และสิ่งที่ใกล้เคียงกับมาตรฐานใน Unices) ไม่ได้ระบุตัวเลือกดังกล่าวสำหรับgrep

ดังที่ได้กล่าวไว้ในคำตอบอื่น ๆ การนำไปใช้ของ GNU grepมีตัวเลือกที่ไม่ได้มาตรฐานซึ่งทำในสิ่งที่คุณต้องการ ในขณะที่การใช้งานเฉพาะนี้อาจเป็นเรื่องปกติในระบบ Linux คุณไม่สามารถสมมติความพร้อมใช้งานของมันบน Unix ใด ๆ แม้แต่ระบบ Linux บางระบบ

ในที่สุดฉันควรจะพูดถึงว่ามันเป็นปรัชญาของ Unixที่สนับสนุนการผสมผสานของโปรแกรมดั้งเดิมหลายโปรแกรมมากกว่าการใช้โปรแกรมประมวลผลแบบเสาหินขนาดใหญ่ที่พยายามทำทุกอย่างในครั้งเดียว

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


0

เพื่อค้นหาสตริงจากไดเรกทอรีที่กำหนดให้ใช้คำสั่งด้านล่าง

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

ตัวอย่างเช่น:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;

1
grepสามารถใช้ไฟล์มากกว่าหนึ่งไฟล์เป็นอาร์กิวเมนต์ได้ดังนั้นคุณควรใช้+แทน\;เพื่อหลีกเลี่ยงการเรียกใช้หนึ่งgrepไฟล์ต่อหนึ่งไฟล์ซึ่งค่อนข้างไม่มีประสิทธิภาพ
Stéphane Chazelas

1
โปรดทราบว่า-name '*'จำกัด เฉพาะไฟล์ที่มีชื่อเป็นข้อความที่ถูกต้องในโลแคลปัจจุบัน (ในfindการใช้งานบางอย่างเป็นอย่างน้อย) แต่ส่วนประกอบไดเรกทอรีอื่นอาจยังคงมีลำดับไบต์ที่ไม่ได้ใช้อักขระที่ถูกต้อง ถ้าคุณตั้งใจด้วย-name '*'คือทำให้แน่ใจว่าผลลัพธ์เป็นข้อความที่ถูกต้อง (โดยการข้ามไฟล์ที่มีชื่อที่ไม่เหมาะสม) คุณควรจะใช้find ... ! -name '*' -prune -o -exec grep ... {} +ซึ่งจะหยุดไม่ให้findลงมาสู่ไดเรกทอรีที่มีชื่อที่ไม่เหมาะสม
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.