วิธีแก้ปัญหาปัจจุบันของฉันจะเป็นfind <expr> -exec printf '.' \; | wc -c
แต่จะใช้เวลานานเกินไปเมื่อมีผลลัพธ์มากกว่า 10,000 รายการ ไม่มีวิธีที่เร็วกว่า / ดีกว่านี้หรือ
วิธีแก้ปัญหาปัจจุบันของฉันจะเป็นfind <expr> -exec printf '.' \; | wc -c
แต่จะใช้เวลานานเกินไปเมื่อมีผลลัพธ์มากกว่า 10,000 รายการ ไม่มีวิธีที่เร็วกว่า / ดีกว่านี้หรือ
คำตอบ:
ลองนี้แทน (ต้อง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
เส้น)
-printf '.'
ทำไมจะไม่ล่ะ
find <expr> | wc -l
เป็นวิธีง่ายๆแบบพกพา? โซลูชันดั้งเดิมของคุณกำลังสร้างกระบวนการใหม่ printf
สำหรับทุกไฟล์ที่พบและมีราคาแพงมาก (เท่าที่คุณพบ)
โปรดทราบว่าสิ่งนี้จะมากเกินไปหากคุณมีชื่อไฟล์ที่มีบรรทัดใหม่ฝังอยู่ แต่ถ้าคุณมีแล้วฉันสงสัยว่าปัญหาของคุณจะเกิดขึ้นอีกเล็กน้อย
โซลูชันนี้ช้ากว่า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) เป็นตัวคั่นลูป
นี่คือ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'