วิธีการตรวจสอบว่า "ค้นหา" พบการแข่งขันใด ๆ หรือไม่


16

มีวิธีการที่ใช้สำนวนในการตรวจสอบว่า "ค้นหา" พบการแข่งขันใด ๆ หรือไม่? ฉันกำลังใช้

COUNT=`find ... | wc -l`
if [ "$COUNT" -gt 0 ]; then

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

อัปเดต:ฉันทำผิดพลาดในการเขียนคำถามโดยไม่มีรหัสอยู่ข้างหน้าฉัน: ฉันใช้wc -lในกรณีอื่นซึ่งฉันจำเป็นต้องทราบจำนวนไฟล์ทั้งหมดที่พบ ในกรณีที่ฉันก็แค่ทดสอบว่ามีการแข่งขันใด ๆ if [ -z $(find …) ]ผมใช้

คำตอบ:


17

หากคุณรู้ว่าคุณมี GNU พบให้ใช้-quit เพื่อหยุดหลังจากการจับคู่ครั้งแรก

portably ท่อส่งออกของเข้าfind head -n 1วิธีfindนั้นจะตายจากไปป์ที่ขาดหลังจากการจับคู่ไม่กี่ครั้ง (เมื่อheadใส่บัฟเฟอร์การป้อนข้อมูลเต็ม)

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

if [ -n "$(find … | head -n 1)" ]; then …

น่าสนใจ ... ฉันคิดว่า-nนำไปใช้กับตัวแปร 'ที่กำหนด' เท่านั้น ($ abc, $ xyz, ฯลฯ ) แต่ฉันคิดว่า $ (... ) เป็นตัวแปรอุณหภูมิ 'ที่กำหนด' .. +1 ... (และฉันเพิ่ง อ่านเมื่อเร็ว ๆ นี้ว่าการใช้-nมีความเสี่ยงเว้นแต่คุณจะแน่ใจว่าตัวแปรดังกล่าวยังไม่ได้ประกาศและไม่ได้ใช้งาน แต่อย่างใด ... แต่อุณหภูมิจะไม่มีความเป็นไปได้นี้ ... เช่น ไม่ได้เตรียมการเทียบกับว่างเปล่า
Peter.O

2
@ เฟร็ด: ในทางกลับกัน-nทดสอบว่าสตริงว่างเปล่าหรือไม่โดยไม่เกี่ยวข้องกับตัวแปร สิ่งที่คุณอ่านอาจจะบอกว่าใช้-nไม่ได้ทดสอบว่าตัวแปรที่ถูกกำหนดให้: -n "$foo"เป็นเท็จถ้าfooมีการกำหนด set -uแต่ว่างเปล่าและแสดงข้อความผิดพลาดภายใต้ [ -n "${foo+1}" ]เชื่อถือได้ทดสอบว่าfooมีการตั้งค่าการรักษา แต่ตัวแปรที่ว่างเปล่าและไม่มีการตั้งค่าเหมือนกันมักจะเป็นความคิดที่ดี[ -n "${foo:+1}" ]หรือเพียงแค่ถ้าคุณไม่ได้กังวลเกี่ยวกับ[ -n "$foo" ] set -u
Gilles 'SO- หยุดความชั่วร้าย'

ขอบคุณ! ฉันไม่-quitสามารถใช้งานได้แต่ใช้head -n 1งานได้ตามปกติ (เช่นเดียวกับhead -c 1ที่หยุดก่อนหน้านี้ แต่อาจได้รับผลประโยชน์เล็กน้อย) นอกจากนี้ฉันทำผิดพลาดในการเขียนคำถามของฉันโดยไม่มีรหัสอยู่ข้างหน้าฉัน: ฉันใช้wc -lในกรณีอื่นที่ฉันต้องรู้จำนวนไฟล์ที่พบทั้งหมด ในกรณีที่ฉันก็แค่ทดสอบว่ามีการแข่งขันใด ๆ if [ -z `find … ` ]ผมใช้
Chris หน้า

6

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

ตัวอย่างเช่นfind ... -print -quitจะพิมพ์เส้นทางของไฟล์แรกที่ตรงกันแล้วออก หรือคุณสามารถใช้-printf 1 -quitพิมพ์ 1 หากมีการจับคู่และไม่มีอะไรถ้าไม่มี

findสถานะการออกของสะท้อนให้เห็นว่ามีข้อผิดพลาดขณะค้นหาหรือไม่และพบว่ามีอะไรหรือไม่ดังนั้นคุณต้องตรวจสอบผลลัพธ์เพื่อดูว่ามีการจับคู่หรือไม่


-quitเป็นนามสกุล GNU มันจะไม่ทำงานกับระบบที่ใช้งานการค้นหา (1) อื่น ๆ เช่น OS X, BSD และ Unices เชิงพาณิชย์ส่วนใหญ่
Warren Young

ขอบคุณมีประโยชน์ที่จะทราบในกรณีที่ฉันใช้ระบบอื่น น่าเสียดายที่ไม่มี -quit หรือ -printf ในเหมือง (Mac OS X)
Chris หน้า

4

Exit 0 นั้นง่ายต่อการค้นหา exit> 0 นั้นยากกว่าเพราะมักจะเกิดขึ้นกับข้อผิดพลาดเท่านั้น อย่างไรก็ตามเราสามารถทำให้มันเกิดขึ้น:

if find -type f -exec false {} +
then
  echo 'nothing found'
else
  echo 'something found'
fi

โปรดทราบว่าวิธีนี้มีประสิทธิภาพมากกว่าการใช้ subshell การดำเนินการ false นั้นเร็วกว่าการดำเนินการแม้แต่ Dash:

$ cat alfa.sh bravo.sh charlie.sh delta.sh
find -name non-existing-file -exec false {} +
find -name existing-file -exec false {} +
[ "$(find -name non-existing-file)" ]
[ "$(find -name existing-file)" ]

$ strace dash alfa.sh | wc -l
807

$ strace dash bravo.sh | wc -l
1141

$ strace dash charlie.sh | wc -l
1184

$ strace dash delta.sh | wc -l
1194

0

คุณสามารถห่อมันให้อยู่ในสภาพของเชลล์เช่น:

[ "$(find . ...)" '!=' '' ] && echo Found || echo Not found

ในกรณีที่เป็นเงื่อนไขการจับคู่ของคุณเช่น...-name *.txt

ตัวอย่างอื่น ๆ :

[ "$(find /etc -name hosts)" ] && echo True || echo False
[ ! -z "$(find /etc -name hosts)" ] && echo True || echo False
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.