วิธีใดที่ดีที่สุดในการนับผลลัพธ์“ ค้นหา”


101

วิธีแก้ปัญหาปัจจุบันของฉันจะเป็นfind <expr> -exec printf '.' \; | wc -cแต่จะใช้เวลานานเกินไปเมื่อมีผลลัพธ์มากกว่า 10,000 รายการ ไม่มีวิธีที่เร็วกว่า / ดีกว่านี้หรือ


ใช้ wc -l กับผลลัพธ์ของคุณ
Manuel Selva

คำตอบ:


86

ลองนี้แทน (ต้องfind's -printfสนับสนุน):

find <expr> -type f -printf '.' | wc -c

มันจะน่าเชื่อถือและรวดเร็วกว่าการนับเส้น

โปรดทราบว่าฉันใช้find's printfไม่ใช่คำสั่งภายนอก


มานั่งกันหน่อย:

$ ls -1
a
e
l
ll.sh
r
t
y
z

เกณฑ์มาตรฐานตัวอย่างข้อมูลของฉัน:

$ time find -type f -printf '.' | wc -c
8

real    0m0.004s
user    0m0.000s
sys     0m0.007s

เต็มบรรทัด:

$ time find -type f | wc -l
8

real    0m0.006s
user    0m0.003s
sys     0m0.000s

ดังนั้นวิธีแก้ปัญหาของฉันเร็วกว่า =) (ส่วนที่สำคัญคือrealเส้น)


6
ไม่เทียบเท่ามันน่าเชื่อถือกว่า =)
Gilles Quenot

6
จะไม่น่าเชื่อถือไปกว่านี้หากไม่รองรับแฟล็ก -printf เพื่อค้นหาบนแพลตฟอร์มของคุณ ;-)
Randy Howard

7
โปรดทราบว่าคุณสามารถโกนออกไปได้อีกไม่กี่นาโนวินาทีโดยไม่อ้างจุดใน-printf '.'
Jens

6
@Jens - โดยเฉพาะอย่างยิ่งเมื่อคุณคำนึงถึงเวลาที่ใช้ในการพิมพ์
Brian Agnew

6
ด้วยเกณฑ์มาตรฐานที่เล็กเช่นนี้การกำหนดเวลาอาจถูกครอบงำโดยปัจจัยอื่นที่ไม่ใช่สิ่งที่คุณต้องการวัด การทดลองกับต้นไม้ใหญ่จะมีประโยชน์มากกว่า แต่นี่ได้รับการโหวตของฉันสำหรับการทำสิ่งที่ OP ขอ
tripleee

134

ทำไมจะไม่ล่ะ

find <expr> | wc -l

เป็นวิธีง่ายๆแบบพกพา? โซลูชันดั้งเดิมของคุณกำลังสร้างกระบวนการใหม่ printfสำหรับทุกไฟล์ที่พบและมีราคาแพงมาก (เท่าที่คุณพบ)

โปรดทราบว่าสิ่งนี้จะมากเกินไปหากคุณมีชื่อไฟล์ที่มีบรรทัดใหม่ฝังอยู่ แต่ถ้าคุณมีแล้วฉันสงสัยว่าปัญหาของคุณจะเกิดขึ้นอีกเล็กน้อย


9
-1: จะแตกไฟล์ด้วยการขึ้นบรรทัดใหม่และช้ากว่าการนับไบต์ =)
Gilles Quenot

23
ฉันไม่คิดว่าจะรับประกันการลงคะแนนเนื่องจากข้อ จำกัด ชื่อไฟล์ / การขึ้นบรรทัดใหม่ค่อนข้างหายากและระบุไว้ข้างต้น ช้าลง? บางที เนื่องจากคุณกำลังค้นหาระบบไฟล์ฉันสงสัยว่าความเร็วแตกต่างกันเล็กน้อย ใน 10,000 ไฟล์ของฉันฉันวัดความแตกต่าง 3ms
Brian Agnew

8
ความแตกต่างของประสิทธิภาพระหว่าง 'find <expr> | wc -l' และ 'find <expr> -printf | wc -c 'มีขนาดเล็กมาก การแคช (เช่นถ้าคุณเรียกใช้การค้นหาเดียวกันสองครั้งบนทรีเดียวกัน) มีความสำคัญกว่ามาก IMHO การแก้ปัญหาด้วย "wc -l" นั้นใช้งานง่ายกว่ามาก
pitseeker

5

โซลูชันนี้ช้ากว่าfind -> wcโซลูชันอื่น ๆที่นี่ แต่ถ้าคุณมีแนวโน้มที่จะทำอย่างอื่นด้วยชื่อไฟล์นอกเหนือจากการนับคุณสามารถทำได้readจากfindผลลัพธ์

n=0
while read -r -d ''; do
    ((n++)) # count
    # maybe perform another act on file
done < <(find <expr> -print0)
echo $n

เป็นเพียงการแก้ไขโซลูชันที่พบใน BashGuide ที่จัดการไฟล์ที่มีชื่อที่ไม่เป็นมาตรฐานอย่างถูกต้องโดยทำให้findตัวคั่นเอาต์พุตเป็นไบต์ NUL โดยใช้print0และอ่านจากมันโดยใช้''(NUL byte) เป็นตัวคั่นลูป


4

นี่คือcountfilesฟังก์ชั่นของฉันในของฉัน~/.bashrc(มันเร็วพอสมควรควรใช้กับ Linux & FreeBSD findและไม่ถูกหลอกโดยเส้นทางไฟล์ที่มีอักขระขึ้นบรรทัดใหม่สุดท้ายwcก็นับไบต์ NUL):

countfiles () 
{ 
   command find "${1:-.}" -type f -name "${2:-*}" -print0 | 
       command tr -dc '\0' | command wc -c;
return 0
}

countfiles

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