ฉันกำลังใช้งานfindและรับรายการไฟล์ที่ฉันต้องการgrepผ่าน ฉันจะไพพ์รายชื่อนั้นได้grepอย่างไร?
ฉันกำลังใช้งานfindและรับรายการไฟล์ที่ฉันต้องการgrepผ่าน ฉันจะไพพ์รายชื่อนั้นได้grepอย่างไร?
คำตอบ:
กรณีทั่วไปที่ทำงานกับคำสั่งใด ๆ ที่เขียนไปยัง stdout คือการใช้xargsซึ่งจะช่วยให้คุณแนบอาร์กิวเมนต์บรรทัดคำสั่งจำนวนเท่าใดก็ได้ที่ส่วนท้ายของคำสั่ง:
$ find … | xargs grep 'search'
หรือเพื่อฝังคำสั่งในgrepบรรทัดของคุณด้วย backticks หรือ$()ซึ่งจะรันคำสั่งและแทนที่ผลลัพธ์:
$ grep 'search' $(find …)
โปรดทราบว่าคำสั่งเหล่านี้จะไม่ทำงานหากชื่อไฟล์มีช่องว่างหรือ“ อักขระแปลก ๆ ” อื่น ๆ ( \'"สำหรับ xargs \[*?สำหรับ$(find …))
อย่างไรก็ตามในกรณีเฉพาะของfindความสามารถในการเรียกใช้โปรแกรมบนอาร์กิวเมนต์ที่กำหนดนั้นมีอยู่แล้วภายใน:
$ find … -exec grep 'search' {} \;
ทุกสิ่งระหว่าง-execและ;เป็นคำสั่งให้ดำเนินการ; จะถูกแทนที่ด้วยชื่อไฟล์ที่พบโดย{} findที่จะดำเนินการแยกต่างหากgrepสำหรับแต่ละไฟล์ เนื่องจากgrepสามารถใช้ชื่อไฟล์จำนวนมากและค้นหาพวกเขาทั้งหมดคุณสามารถเปลี่ยน;เพื่อ+ที่จะบอกหาที่จะผ่านทั้งหมดชื่อไฟล์ที่ตรงกันไปgrepในครั้งเดียว:
$ find … -exec grep 'search' {} \+
find ... -type f -print0 | xargs -r0 grep 'search' /dev/nullฉันชอบ QED ในขณะที่-exec +มีประสิทธิภาพมากมันไม่ได้มีอยู่ในทุกรุ่นของการค้นหา
$ find … -exec grep 'search' {} \+รูปแบบเป็นมากเร็วที่สุด
บางรุ่นของgrep(เช่นบน Linux หรือBSDหรือ Mac OS X ที่ไม่ได้ฝังตัว) มี-rตัวเลือกเพื่อทำการค้นหาแบบเรียกซ้ำ บน OpenBSD ใช้-R(และไม่มี--excludeตามตัวอย่างด้านล่าง) นี้ครอบคลุมถึงชุดที่เรียบง่ายของด้วยfindgrep
หากการดำเนินการของคุณไม่ได้มี-Rธงหรือถ้าคุณต้องการเกณฑ์ไฟล์จับคู่นักเล่น, คุณสามารถใช้-execหลักของการที่จะทำให้มันรันfind grepการfindใช้งานรุ่นเก่าบางอย่างไม่สนับสนุน-exec... +; ในระบบเหล่านี้ใช้;แทน+(จะเรียกgrepหนึ่งครั้งต่อไฟล์ดังนั้นมันจะช้าลง แต่ไม่เช่นนั้นผลลัพธ์จะเหมือนกัน) สังเกต/dev/nullเคล็ดลับที่จะทำให้grepชื่อไฟล์แม้ว่ามันจะเกิดขึ้นกับไฟล์เดียว (GNU grep และ FreeBSD / NetBSD / OSX grep มี-Hตัวเลือกเพื่อให้ได้ผลเหมือนกัน)
find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
GNU grepมี-Hตัวเลือกให้พิมพ์ชื่อไฟล์เสมอ