ฉันจะหยุดการค้นหาจากมากไปน้อยในไดเรกทอรีที่พบได้อย่างไร


24

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

ดังนั้นฉันไม่ต้องการเสียเวลากับ./my-search-term/dir/my-search-termฯลฯ

ฉันจะหยุดการเรียกซ้ำเมื่อฉันพบไดเรกทอรีของฉันคำค้นหาแรกได้อย่างไร


3
คุณเคยลองค้นหาด้วย -prune แล้วหรือยัง? จาก man page: "ถ้าไฟล์เป็นไดเรกทอรีห้ามลงไปในนั้นถ้าได้รับ -depth, false; ไม่มีผลเนื่องจาก -delete หมายถึง -depth คุณไม่สามารถใช้ -prune และ -delete ร่วมกันได้"
laebshade

1
@ laebshade ทำไมคุณไม่ลองใส่คำตอบล่ะ?
jw013

@ jw013 ฉันไม่มีเวลาที่จะให้คำตอบที่ลึกซึ้งยิ่งขึ้นในเวลานั้น
laebshade

คำตอบ:


17

การ-pruneดำเนินการจะfindไม่ถูกเรียกคืนไปยังไดเรกทอรี คุณสามารถรวมเข้ากับการกระทำอื่นเช่น-exec(ลำดับ-pruneและ-execไม่สำคัญตราบใดที่-pruneมีการดำเนินการด้วยวิธีใดวิธีหนึ่ง)

find . -name my-search-term -prune -exec find {} … \;

โปรดทราบว่าการทำรังfindอยู่ภายในfind -execอาจจะเป็นปัญหาเล็ก ๆ น้อย ๆ : คุณไม่สามารถใช้-execในด้านเพราะเทอร์มิจะถูกมองว่าเป็นเทอร์มิจากด้านนอกได้find findคุณสามารถหลีกเลี่ยงปัญหานี้ได้ด้วยการเรียกใช้เชลล์ แต่ระวังการอ้างอิง

find . -name my-search-term -prune -exec sh -c '
    find "$@" … -exec … {\} +
' _ {} +

วงเล็บในคำสั่งแรกของคุณจำเป็นหรือไม่? -pruneผลตอบแทนที่แท้จริง-execและสามารถใส่ก่อน
rozcietrzewiacz

@rozcietrzewiacz ไม่พวกมันไม่จำเป็น นิสัยของการมี-oในนั้นฉันเดา และฉันเดาว่าการวาง-pruneก่อนหน้า-execนั้นสามารถอ่านได้มากขึ้น
Gilles 'หยุดความชั่วร้าย'

ขอขอบคุณอย่าใช้-pruneตัวเลือกก่อนหน้านี้
haridsv

ในกรณีที่ใช้งานของฉัน, คำสั่งนี้จะช่วยให้ข้อผิดพลาด:mkdir -p x1 x2; touch x1/x11 x1/x12 x2/x21 x2/x22; find . -name 'x1*' -exec rm -rf {} \; find: ./x1: No such file or directoryการแก้ปัญหาคือการเพิ่ม-pruneในตอนท้ายของfindคำสั่ง
haridsv

(1) บางรุ่นfindขยาย{}แม้เมื่อมันปรากฏเป็น substring -execของการโต้แย้งไปยัง รุ่นดังกล่าวของfindจะสำลักคำสั่งที่สองของคุณเพราะ{}ในด้านfindคำสั่ง (ในคำสั่ง shell) findจะถูกแทนที่ด้วยชื่อของไดเรกทอรีที่พบในด้านนอก คุณสามารถแก้ไขปัญหาด้วยการพูดว่าfind . -name my-search-term -prune -exec sh -c 'find "$0" … -exec … "{"} +' {} \; คือใช้ซึ่งเปลือกจะเปลี่ยนเป็น"{"} {}... (ต่อ)
สกอตต์

6

- โซลูชั่นเปลือย -

หากคุณต้องการfindข้ามเนื้อหาของไดเรกทอรีที่พบ แต่ค้นหาในไดเรกทอรีอื่นต่อให้ใช้-prune@laebshade ที่แนะนำ คำสั่งแบบเต็มควรมีลักษณะเช่นนั้น

 find . -type d -name somename -prune -exec ...

ในทางกลับกันถ้าคุณต้องการfindที่จะทั้งหมดหยุดการค้นหาและหลังจากการค้นหาไดเรกทอรีจับคู่แรกแล้วสิ่งที่คุณกำลังมองหาอยู่-quit(ใช้ได้ตั้งแต่รุ่น4.2.3ของGNU find) อันนี้ค่อนข้างยุ่งยากกว่าที่จะใช้เพราะทำให้findออกทันที - ดังนั้น-quitต้องวางที่ส่วนท้ายสุดของคำสั่ง:

find . -type d -name somename -exec ... -quit

เพื่อให้การทำงานเป็นไปตามที่คาดไว้เราต้องรับรองว่า-execผลตอบแทนที่แท้จริง (ในคำอื่น ๆ คือสถานะเป็นศูนย์ ) หากคุณต้องการให้สถานะการออก-execถูกเพิกเฉยเพื่อให้ใช้-quitงานได้ตลอดเวลาคุณต้องมีเคล็ดลับเล็กน้อย:

find . -type d -name somename \( -exec ... -o -true \) -quit

หรือ

find . -type d -name somename \( -exec ... -o -quit \)

หรือ

find . -type d -name somename \( -exec ... , -quit \) # a comma before -quit

- คำอธิบายบางอย่าง -

สิ่งที่สำคัญที่สุดเกี่ยวกับวิธีการfindทำงานคือการกระทำทั้งหมด("การทดสอบ")ได้รับการปฏิบัติเหมือนภาคตรรกะตีความจากซ้ายไปขวา ดังนั้นการดำเนินการที่ผ่านมา (ตัวอย่าง-quit) จะได้รับการดำเนินการหากส่วนที่ก่อนหน้านี้ทั้งหมดไม่ได้กลับเท็จ โดยค่าเริ่มต้นการทดสอบทั้งหมดจะถูกรวมเข้ากับตรรกะ "AND" -oตัวเลือกจะเปลี่ยนการเชื่อมต่อเป็น "OR"

องค์ประกอบที่ซับซ้อนของ-oคือfindสามารถ "เพิ่มประสิทธิภาพ" คำสั่งของคุณและไม่เรียกใช้-execส่วนถ้าคุณพิมพ์เพียง

find . -type d -name somename -exec ... -o -quit

เพื่อรับมือกับสิ่งนั้นคุณสามารถบังคับfindให้ประเมินเพรดิเคตทั้งหมดที่มี "OR" โดยใส่ไว้ในวงเล็บ

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