2013-03-27 8 views

答えて

87

なぜないシンプルなポータブルソリューションとして

find <expr> | wc -l 

?元の解決策は、見つかった個々のファイルごとに新しいプロセスprintfを作成することです。これは(見つかったばかりの)非常に高価です。これはあなたが埋め込まれた改行を含むファイル名を持っている場合、オーバーしていますが、その後、私はあなたの問題ではなく、これを試してみてください

+5

-1:改行でファイルが壊れてしまいます。= –

+11

ファイル名/改行の制限が非常にまれであることを考えると、 *と*は上記のとおりです。もっとゆっくり ?おそらく。あなたがファイルシステムに問い合わせているとすれば、私は速度の違いが小さいと思っています。私の10,000ファイルの間で私は3msの差を測定する –

+2

'find | wc -l'と ' -printfを見つけるのパフォーマンスの違い。 | wc -c 'は非常に小さい。キャッシング(つまり、同じツリー上で同じ検索を2回実行する場合)はさらに重要です。 IMHO "wc -l"のソリューションは、より直感的です。 – pitseeker

39

:-)少し深く実行疑うことがあれば(find-printfサポートを必要とする)すること

注:

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

これは、行を数えるよりも信頼性が高く、高速になります。

外部コマンドではなく、findprintfを使用します。


レッツ・ベンチビット:

$ 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 

だから私のソリューションは高速です=)(重要な部分はです0ライン)

+0

@RandyHoward見つかった各ファイルの1つのドットは、見つかった各ファイルの1行に相当します。 –

+4

同等ではなく、より信頼性があります=) –

+0

ありがとう@MichaelFoukarakis、私は十分に見ていませんでした。おそらく、その使用法がここでは機能しないため、-printfは今使っているOS X上のfindにとって有効なオプションではありません。それはgnu拡張ですか?しかしこれはうまくいく:find -type f -exec printf '。' \ l; | wc -l –

2

は、これが私の中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' 
2

このソリューションは、ここで他のfind -> wcソリューションの一部よりも確かに遅いですが、あなたはそれらをカウントに加えて、ファイル名を持つ他の何かを行うに傾いていた場合、あなたはfind出力のreadになります。

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

それが適切print0を使用してNULバイト区切りfind出力を行うと、ループの区切り文字として''(NULバイト)を使用して、そこから読み取ることによって、非標準の名前のファイルを扱うBashGuideで見つかったa solutionの単なる変形例であり、 。

-1

私はスピード競争でつまずくときに私は大好きです。検索/トイレを使用する場合と比較して ``

$ 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 

: - トイレを使用して間違っている、しかし限り、私たちはベンチマーキングしていると何もここでは、ほとんどのポータブルかつ最速の解決策(と思う)ではありません

$ 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 

隠しファイルを考慮する必要がある場合は、forループに2つの引数を持たなければならないことに注意してください。for devfile in /dev/.* /dev/*; do ...そして、それはもっと速くなります。

ハッピーハッキング!

+3

'find'とbash globbingは同じではありません。ディレクトリを使って検索を行いますが、デフォルトでシェルのグロブは検索しません。 –

+0

@ MechMK1正しいですが、このメソッドの再帰性はありません。おそらくそれはずっと速いのです。 –

+4

また、実際のコメントが実行される前にbashが実際にglobbing *を拡張するので、実際にアイテムを見つけるのに時間がかかるプロセスは、 'time'が実行される前に行われます。 –

関連する問題