`findよりも速いものはありますか?| wc -l`はディレクトリ内のファイルをカウントしますか?


8

珍しいことではありませんが、ディレクトリ内のファイル数を数える必要があります。数百万に達する場合もあります。

単にそれらを列挙して数えるよりも良い方法はありfind . | wc -lますか?I / Oの負荷が少ないext3 / 4で実行できるファイルシステム呼び出しの種類はありますか?


3
ファイルだけでなくディレクトリも数えています。ファイルのみをカウントする場合は、「
find。

ディレクトリは、デバイス、シンボリックリンク、ソケットと同様に一種のファイルです。通常のファイルはファイルのサブセットです。
Toby Speight 2017

1
あなたが与える例は、あなたが再帰的なカウントを望んでいることを示唆しています-そうでないなら、あなたは必要find -maxdepth 1です。現在のアプローチでは、改行文字を含む名前はすべて二重にカウントされることに注意してください。
Toby Speight 2017

回答:


13

基本的なスピードアップではなく、少なくとも何か:)

find . -printf \\n | wc -l

ファイル名のリストを渡す必要はなく、改行で十分です。このバリアントは、ディレクトリがRAMにキャッシュされている場合、Ubuntu 12.04.3で約15%高速です。さらに、このバリアントは改行を含むファイル名で正しく動作します。

興味深いことに、この亜種は上記のものより少し遅いようです:

find . -printf x | wc -c

特別なケース-しかし、本当に速い

ディレクトリが独自のファイルシステム上にある場合は、単にiノードを数えることができます。

df -i .

カウントされたディレクトリ以外のディレクトリおよびファイルの数がほとんど変わらない場合は、現在のdf -i結果からこの既知の数を単に差し引くことができます。このようにして、ファイルとディレクトリを非常に迅速に数えることができます。


「このバリアントは約15%高速です...」これらの時間を計るために使用しているある種の便利なトリックがあるのだろうか?
Brian Z

4
@BrianZ:コマンドの前に時間を付けることで、コマンドの時間を計ることができます。time find /usr/src/ -printf \\n | wc -l、実行の合間にキャッシュをクリアできますsudo sync && sudo sysctl -w vm.drop_caches=3
MattPark

したがって、キャッシングなしで最初の2つのオプションのいずれかを使用すると、速度が一貫して2%向上しました。ええ、それはかなりクールな方法です。iノードを数えるのは、環境がそのように設定されている場合に間違いなく最適です。私はそれを考えていませんでした。
MattPark 2013

-printf xと同じであることを意図-printf '\0'?ドキュメントに記載されていません。
CMCDragonkai 2018年

@CMCDragonkai:アクションはC -printfprintf()関数と同様に機能しますが、主な違いは、%ディレクティブの意味が異なることです。アクションは、見つかったすべてのファイルに対して呼び出されます。つまり、これは、見つかったすべてのファイル-printf xの文字xを印刷し(試してみてください!)、見つかったすべてのファイル-printf '\0'の文字NULL(ASCIIコード0)を印刷します。-printf '\0'特別な意味はありません。wc -cこの回答の例では、どちらも同じように機能します。
pabouk 2018年

3

私はまさにその目的のためにffcntを書きましたfiemapioctlを使用してディレクトリ自体の物理オフセットを取得し、ランダムアクセスを減らすために、複数の順次パスでディレクトリトラバーサルをスケジュールします。と比較して実際に速度が向上するかどうかfind | wc は、いくつかの要因に依存します。

  • ファイルシステムのタイプ:fiemapioctl をサポートするext4などのファイルシステムが最もメリットがあります
  • ランダムアクセス速度:HDDはSSDよりはるかに優れています
  • ディレクトリレイアウト:ネストされたディレクトリの数が多いほど、最適化の可能性が高くなります

(すべての方法で)を使用して(relatimeまたは)マウントするとnodiratime、アクセスがメタデータの更新を引き起こす場合、速度が向上します(すべての方法)。


最後の文は価値のあるヒントです!プログラムのしくみの概要を追加すると、プログラムへのリンクが改善されると思います。リンクされたリソースに問題が発生した場合に備えて、回答自体が完全なものをお勧めします(もちろんリンクも保持します)。
Toby Speight 2017

2

実際、私のシステム(Arch Linux)では、このコマンド

   ls -A | wc -l

上記のすべてよりも高速です:

   $ time find . | wc -l
  1893

   real    0m0.027s
   user    0m0.004s
   sys     0m0.004s
   $ time find . -printf \\n  | wc -l
   1893

   real    0m0.009s
   user    0m0.000s
   sys     0m0.008s
   $ time find . -printf x  | wc -c
   1893

   real    0m0.009s
   user    0m0.000s
   sys     0m0.008s
   $ time ls -A | wc -l
   1892

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

lsの問題は、/bin/ls: Argument list too longグロビングを使用する場合と同様に返されることが多いことですが、findのように再帰的に動作できるため、検討する必要がある場合があるため、必要ない場合はfindを使用しないでください。
MattPark 2013

コメントするのは遅い(何年も)ようls -Aですが、現在のディレクトリにあるファイルのみをリストし、引数findなしで-maxdepth 1はすべてのサブディレクトリを再帰的に検索します。
Luciano、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.