มีวิธีบังคับให้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 ดังนั้นจึงไม่ยุ่งกับเอาต์พุตคำสั่งซึ่งหมายความว่าไพพ์หรือการเปลี่ยนเส้นทางจะออกเพียงบรรทัด จับคู่ด้วยการค้นหา