วิธีการรวมค้นหาและ grep สำหรับการค้นหาที่ซับซ้อน? (GNU / linux, find, grep)


17

ฉันพยายามค้นหาข้อความในไฟล์บางไฟล์ที่ใช้โครงสร้างไดเรกทอรีร่วมกัน แต่ไม่ได้อยู่ในแผนผังไดเรกทอรีเดียวกันใน GNU / Linux

ฉันมีเว็บเซิร์ฟเวอร์ที่มีหลาย ๆ ไซต์ที่ใช้โครงสร้างแบบต้นไม้เดียวกัน (Code Igniter MVC PHP framework) ดังนั้นฉันต้องการค้นหาในไดเรกทอรีที่เฉพาะเจาะจงลงบนต้นไม้สำหรับแต่ละไซต์ตัวอย่าง:

/srv/www/*/htdocs/system/application/

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

ฉันรู้วิธีใช้findและgrepแต่ฉันไม่เก่งในการรวมเข้าด้วยกัน

ฉันจะทำสิ่งนี้ได้อย่างไร
ขอบคุณล่วงหน้า!

คำตอบ:


21

ลอง

find /srv/www/*/htdocs/system/application/ -name "*.php" -exec grep "debug (" {} \; -print

นี้ซ้ำควรค้นหาโฟลเดอร์ที่อยู่ภายใต้applicationสำหรับไฟล์ที่มีนามสกุลและส่งพวกเขาไป.phpgrep

การเพิ่มประสิทธิภาพนี้จะดำเนินการ:

find /srv/www/*/htdocs/system/application/ -name "*.php" -print0 | xargs -0 grep -H "debug ("

สิ่งนี้ใช้xargsเพื่อส่ง.phpออกไฟล์ทั้งหมดโดยfindเป็นข้อโต้แย้งไปยังgrepคำสั่งเดียว เช่น. ตัวเลือกในการและตัวเลือกในการให้แน่ใจว่าช่องว่างในชื่อไฟล์และไดเรกทอรีที่มีการจัดการอย่างถูกต้อง ตัวเลือกที่ส่งผ่านไปยังเพื่อให้แน่ใจว่าชื่อไฟล์จะถูกพิมพ์ในทุกสถานการณ์ (โดยค่าเริ่มต้นให้พิมพ์ชื่อไฟล์เฉพาะเมื่อมีการส่งผ่านอาร์กิวเมนต์จำนวนมากเท่านั้น)grep "debug (" file1 file2 file3-print0find-0xargs-Hgrepgrep

จากผู้ชาย xargs:

-0

      ไอเท็มอินพุตถูกยกเลิกด้วยอักขระ null แทนช่องว่างและเครื่องหมายคำพูดและแบ็กสแลชไม่ได้เป็นพิเศษ (ทุกตัวอักษรถูกใช้อย่างแท้จริง) ปิดใช้งานจุดสิ้นสุดของสตริงไฟล์ซึ่งถือว่าเหมือนกับอาร์กิวเมนต์อื่น ๆ มีประโยชน์เมื่อรายการอินพุตอาจมีช่องว่างเครื่องหมายคำพูดหรือแบ็กสแลช -print0ตัวเลือกGNU find สร้างอินพุตที่เหมาะสมสำหรับโหมดนี้


1
+1 ที่จะดำเนินการ grep สำหรับไฟล์ php แต่ละไฟล์ หากมีไฟล์จำนวนมากคุณสามารถเพิ่มประสิทธิภาพได้อีกด้วยfind /srv/www/*/htdocs/system/application/ -name "*.php" -print0 | xargs -0 grep "debug ("
Jukka Matilainen

@jackem เห็นด้วย ฉันจะอัปเดตคำตอบของฉันตาม
nagul

2
การปรับปรุงเล็ก ๆ อีกอย่างหนึ่ง: xargs อาจส่งผ่านชื่อไฟล์หนึ่งไปยัง grep ซึ่งในกรณีนี้ grep จะไม่แสดงชื่อไฟล์หากมีการจับคู่ คุณอาจต้องการเพิ่ม -H ลงในคำสั่ง grep เพื่อบังคับให้แสดงชื่อไฟล์
Randy Orrison

@ แรนดี้นั่นเป็นจุดที่ถูกต้องมาก
nagul

3
นี่คือความจริงที่แท้จริง แต่GNU findสามารถนำ+โอเปอเรเตอร์แทน\;การดำเนินการกระบวนการเดียวที่xargsทำ ดังนั้นfind /srv/www/*/htdocs/system/application/ -name "*.php" -exec grep -H "debug (" {} +ทำสิ่งเดียวกันกับxargsตัวอย่างในคำตอบนี้ แต่มีหนึ่งกระบวนการน้อยกว่า (และยังมีความเสี่ยง 0 สำหรับปัญหาชื่อไฟล์)
Daniel Andersson

10

findไม่จำเป็นแม้แต่กับตัวอย่างนี้เราสามารถใช้grepโดยตรง (อย่างน้อยGNU grep):

grep -RH --include='*.php' "debug (" /srv/www/*/htdocs/system/application/

และเราลงสู่กระบวนการแยกเดี่ยว

ตัวเลือก:

  • -R, --dereference-recursive Read all files under each directory, recursively. Follow all symbolic links, unlike -r.
  • -H, --with-filename Print the file name for each match. This is the default when there is more than one file to search.
  • --include=GLOB Search only files whose base name matches GLOB (using wildcard matching as described under --exclude).
  • --exclude=GLOB Skip any command-line file with a name suffix that matches the pattern GLOB, using wildcard matching; a name suffix is either the whole name, or any suffix starting after a / and before a +non-/. When searching recursively, skip any subfile whose base name matches GLOB; the base name is the part after the last /. A pattern can use *, ?, and [...] as wildcards, and \ to quote a wildcard or backslash character literally.

สำหรับความอยากรู้อยากเห็น-RHตัวเลือกหมายถึงอะไร?
กัส

@Gus: เพิ่มman grepข้อความที่ตัดตอนมาจากคำอธิบายตัวเลือกในโพสต์
Daniel Andersson

0

เชลล์ของคุณสามารถค้นหาไฟล์ php และมอบให้กับ grep ในทุบตี:

shopt -s nullglob globstar
grep searchterm /srv/www/*/htdocs/system/application/**/*.php
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.