มีวิธีบังคับให้findคำสั่งหยุดทันทีหลังจากค้นหาคู่แรกหรือไม่
มีวิธีบังคับให้findคำสั่งหยุดทันทีหลังจากค้นหาคู่แรกหรือไม่
คำตอบ:
ด้วย GNU หรือ FreeBSD findคุณสามารถใช้เพรดิเคต-quit:
find . ... -print -quit
NetBSD findเทียบเท่า:
find . ... -print -exit
หากสิ่งที่คุณทำคือการพิมพ์ชื่อและสมมติว่าชื่อไฟล์ไม่มีอักขระขึ้นบรรทัดใหม่คุณสามารถทำได้:
find . ... -print | head -n 1
ที่จะไม่หยุดfindหลังจากการแข่งขันครั้งแรก แต่อาจขึ้นอยู่กับเวลาและบัฟเฟอร์ในการแข่งขันครั้งที่สองหรือ (มาก) ในภายหลัง โดยทั่วไปfindจะถูกยกเลิกด้วย SIGPIPE เมื่อพยายามส่งออกบางสิ่งในขณะที่headหายไปเพราะอ่านแล้วและแสดงบรรทัดแรกของอินพุต
โปรดทราบว่าเปลือกบางส่วนจะไม่รอfindคำสั่งนั้นหลังจากheadส่งคืนแล้ว บอร์นเชลล์และการใช้งาน AT&T ของksh(เมื่อไม่ใช่แบบอินเทอร์แอคทีฟ) และyash(เฉพาะในกรณีที่ไพพ์ไลน์นั้นเป็นคำสั่งสุดท้ายในสคริปต์) จะไม่ปล่อยให้มันทำงานในพื้นหลัง หากคุณต้องการเห็นพฤติกรรมดังกล่าวในเชลล์ใด ๆ คุณสามารถเปลี่ยนข้างต้นเป็น:
(find . ... -print &) | head -n 1
หากคุณกำลังทำมากกว่าการพิมพ์พา ธ ของไฟล์ที่พบคุณสามารถลองวิธีนี้:
find . ... -exec sh -c 'printf "%s\n" "$1"; kill "$PPID"' sh {} \;
(แทนที่printfด้วยสิ่งที่คุณจะทำกับไฟล์นั้น)
นั่นคือผลข้างเคียงของการfindคืนสถานะทางออกซึ่งสะท้อนถึงความจริงที่ว่ามันถูกฆ่า
ที่จริงแล้วการใช้สัญญาณ SIGPIPE แทนที่จะเป็น SIGTERM ( kill -s PIPEแทนที่จะเป็นkill) จะทำให้เปลือกหอยบางตัวเงียบกว่าเกี่ยวกับความตายนั้น (แต่จะยังคงสถานะการออกที่ไม่ใช่ศูนย์)
if [[ $(find ... -print -quit) ]]; then ...เพียงแค่ทดสอบว่าค้นหาสิ่งที่พิมพ์ออกมาหรือไม่
$(…)ส่วนของเครื่องหมายอัญประกาศในกรณีที่คุณใช้เพียงวงเล็บเดียว ( [ … ])
[เป็นคำสั่งมาตรฐาน มันไม่มากคำสั่งที่น่ากลัว แต่วิธีเชลล์เหมือน Bourne แยกบรรทัดคำสั่ง [[...]]เป็นโครงสร้าง ksh ที่มีปัญหาของตัวเองในเปลือกหอยต่างๆ ตัวอย่างเช่นจนกระทั่งเมื่อเร็ว ๆ นี้[[ $(...) ]]จะไม่ทำงานzsh(คุณต้องการ[[ -n $(...) ]]) ยกเว้นในzshคุณต้องมีเครื่องหมายอัญประกาศคู่[[ $a = $b ]]ซึ่ง[[ =~ ]]มีความแตกต่างที่เข้ากันไม่ได้ระหว่างการนำไปใช้งานและระหว่างเวอร์ชันสำหรับ bash และข้อบกพร่องหลายรายการในบางรายการ [ส่วนตัวผมชอบ
...อะไร .
find . -name something -print -quit
ยุติการค้นหาหลังจากการจับคู่ครั้งแรกหลังจากพิมพ์
ยุติการค้นหาหลังจากจำนวนการจับคู่และผลการพิมพ์ที่ระบุ:
find . -name something -print | head -n 5
น่าประหลาดใจมากพอ - ตอนนี้หัวหน้าจบสายหลังจาก 5 แมตช์ แต่ฉันไม่รู้ว่าทำไมหรืออย่างไร
มันง่ายมากที่จะทดสอบ เพียงแค่ให้ค้นหาค้นหาบนรากซึ่งจะส่งผลพันแมตช์อาจจะมากยิ่งขึ้นในขณะที่การไม่น้อยกว่าหนึ่งนาทีหรือมากกว่า แต่เมื่อ piped ไปที่ "head" "find" จะสิ้นสุดหลังจากจำนวนบรรทัดที่ระบุไว้ใน head (head เริ่มต้นแสดง 10 ให้ใช้ "head -n" เพื่อระบุ lines)
โปรดทราบว่าการดำเนินการนี้จะยุติหลังจาก "head -n" ถึงจำนวนอักขระบรรทัดใหม่ที่ระบุดังนั้นการจับคู่ใด ๆ ที่มีอักขระขึ้นบรรทัดใหม่หลายรายการจะนับตามนั้น
เพื่อความบันเทิงนี่คือตัวสร้างการค้นหาที่ขี้เกียจใน Bash ตัวอย่างนี้สร้างเสียงเรียกเข้าไฟล์ในไดเรกทอรีปัจจุบัน อ่านหลาย ๆ เรื่องที่คุณต้องการkill %+(อาจจะแค่ 1)
#!/usr/bin/env bash
unset -v files n
trap 'kill "$x_PID"' EXIT
coproc x while :; do
find . -type f -maxdepth 1 -exec sh -c "$(</dev/fd/3)" _ {} +
done 4<&0 <<\EOF 3<&0 <&4-
for x; do
read -r _
printf '%s\0' "$x"
done
EOF
while
echo >&${x[1]}
IFS= read -rd '' -u "$x" 'files[n++]'
do
printf '%q ' "${files[@]}"
echo
sleep .2
done
grep จะส่งคืนถ้าใช้กับแฟล็-mกด้วยเช่นกัน
find stuff | grep -m1 .
มันจะกลับมาหลังจากบรรทัดแรกที่พิมพ์โดยค้นหา
ความแตกต่างระหว่างสิ่งนี้และfind stuff -print -quit | head -1คือถ้าการค้นหาเร็ว grep มากพออาจไม่สามารถหยุดกระบวนการได้ทันเวลา (ไม่สำคัญเลยจริงๆ) ในขณะที่ถ้าการค้นหายาวเกินไปก็จะพบว่าพิมพ์ไม่จำเป็นมาก เส้น
สิ่งนี้จะใช้งานได้กับ busybox find แม้ว่าจะเป็น grep busybox -mก็ไม่จำเป็นต้องใช้เช่นกัน
find /tmp/stuff -exec "sh" "-c" "eval 'echo {}; { kill \$PPID; }'" \;
สิ่งนี้จะคายข้อความเกี่ยวกับกระบวนการค้นหาที่ได้รับสัญญาณ sigterm (ปกติ) แต่เอาต์พุตนี้เป็นของเชลล์ที่กำลังรันไม่ใช่คำสั่ง find ดังนั้นจึงไม่ยุ่งกับเอาต์พุตคำสั่งซึ่งหมายความว่าไพพ์หรือการเปลี่ยนเส้นทางจะออกเพียงบรรทัด จับคู่ด้วยการค้นหา