วิธีแก้ปัญหาปัจจุบันของฉันจะเป็น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'