2013-03-27 16 views

cevap

87

Neden basit taşınabilir bir çözüm olarak

find <expr> | wc -l 

? Orijinal çözümünüz, bulunan her bir dosya içinprintf numaralı yeni bir prosesi ortaya çıkaran şeklindedir ve bu çok pahalıdır (yeni bulduğunuz gibi). Bu gömülü satırsonu ile dosya varsa overcount, ancak o zaman senin sorunların yerine bu deneyin

+5

-1: yeni satırlarla dosyada kopacak ve bayt saymadan daha yavaş olacak =) –

+11

Hayır, dosya adının/satırsonu sınırlamasının oldukça az olduğu düşünülen bir indirme hatası olduğunu düşünmüyorum * ve * yukarıda belirtilen. Yavaş ? Belki. Bir dosya sistemini sorguladığınızdan, hız farkının küçük olduğundan şüpheliyim. 10.000 dosyamda 3ms farkını ölçüyorum –

+2

' | wc -l' ve 'bulmak -printf arasındaki performans farkı. wc -c 'son derece küçüktür. Önbelleğe alma (yani aynı bulguyu aynı ağaç üzerinde iki kez çalıştırırsanız) çok daha önemlidir. IMHO "wc -l" ile çözüm çok daha sezgisel. – pitseeker

39

:-) biraz daha derin çalıştırmak şüpheli varsa (find 'ın -printf desteği gerektiren) olacağı

Not:

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

Çizgileri saymadan daha güvenilir ve hızlı olacaktır.

Not: find 'un printf numarasını kullanın, harici bir komut değil.


edelim tezgah biraz:

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

Benim pasajı kriter: Tam hatlarıyla

$ 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 

Yani benim çözüm = hızlıdır) (önemli kısım real hat)

+0

@RandyHoward Bulunan her bir dosya için bir nokta, bulunan her dosya için bir satıra eşdeğerdir. –

+4

Eşdeğer değil, daha güvenilir =) –

+0

Teşekkürler @MichaelFoukarakis, yeterince yakından bakmadım. Muhtemelen bu kullanım burada çalışmadığı için, -printf şimdi kullanmakta olduğum OS X'de bulmak için geçerli bir seçenek değildir. Bu bir gnu uzantısı mı? Bu işe yarar: -type f -exec printf 'öğesini bulun. \ I; | wc -l –

2

Bu benim countfiles fonksiyonudur benim ~/.bashrc (Linux & FreeBSD find için çalışmalı, makul, hızlıdır ve yeni satır karakterleri içeren dosya yolları tarafından aptal değildir; Nihai wc sadece NUL bayt) sayar:

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

countfiles 

countfiles ~ '*.txt' 
2

Bu çözüm burada diğer find -> wc çözümlerden bazıları daha kesinlikle yavaştır, ancak onları, sizi sayılmasına ek olarak dosya adları ile başka bir şey yapmak eğimli olsaydı , find çıkışından olabilir.

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

Düzgün print0 kullanarak bir boş karakterle ayırıcı find çıktısını oluşturmak ve döngü sınırlayıcı olarak '' (boş karakter) kullanarak ondan okuyarak standart olmayan isimlerle dosyalarını işleme BashGuide bulunan a solution sadece bir değişiklik olduğunu .

-1

Hız yarışmasına katlandığım zamanları seviyorum.wc kullanarak yanlış, ama sürece biz kıyaslama konum olarak hiçbir şey - burada (Sanırım) en çok taşınabilir ve en hızlı çözüm:

$ time find /dev/sd*[a-z] | wc -l 
25 

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

$ time find /dev/sd*[a-z] -printf . | wc -c 
25 

real 0m0.005s 
user 0m0.000s 
sys  0m0.000s 
: ``

$ time (i=0; for d in /dev/sd*[a-z]; do ((i++)); done; echo $i) 
25 

real 0m0.001s 
user 0m0.000s 
sys  0m0.000s 

bulmak/wc kullanılmasıyla karşılaştırıldığında

Gizli dosyaları hesaba katmanız gerekiyorsa, for döngüsünüzde 2 argümanınız olması gerektiğini unutmayın: for devfile in /dev/.* /dev/*; do ... Ve yol daha hızlı kalır.

Mutlu hack!

+3

'find' ve bash globbing aynı değil. Varsayılan olarak kabuk globbing yokken, dizinlerde aramaları bulun. –

+0

@ MechMK1 bu doğru, bu yöntemin hiçbir özyinelemesi olmayacak - muhtemelen neden bu kadar çok daha hızlıdır –

+4

Ayrıca yöntemin çok daha hızlı olduğuna inanıyorum çünkü bash gerçekte globbing'i * genişletir * gerçek yorum çalıştırılır ve , gerçekte eşya bulmak için zaman harcayan süreç 'zaman' çalıştırılmadan önce yapılır. –

İlgili konular