19

Cルーチンopendir()、readdir()、closedir()は、ディレクトリ構造をトラバースする方法を提供します。ただし、readdir()によって返される各dirent構造体は、ディレクトリサブディレクトリに再帰する必要があるDIRへのポインタのセットを取得するための便利な方法を提供していないようです。

もちろん、ファイルの名前が表示されるので、その名前をディレクトリパスに追加してstat()とopendir()を実行するか、chdir()を使用してプロセスの現在の作業ディレクトリを変更してロールすることができます。 chdir( "..")を介して戻ります。

最初のアプローチの問題は、ディレクトリパスの長さが十分に長い場合、それを含む文字列をopendir()に渡すコストが、ディレクトリを開くコストを過大評価することです。もう少し理論的であれば、複雑さが線形時間を超えて増加する可能性があると言えます(ディレクトリツリー内の(相対的な)ファイル名の合計文字数)。

また、2番目のアプローチには問題があります。各プロセスには現在の作業ディレクトリが1つあるため、マルチスレッドアプリケーションでは1つを除くすべてのスレッドをブロックする必要があります。また、現在の作業ディレクトリが単なる便宜であるかどうかもわかりません(つまり、ファイルシステムクエリの前に相対パスが追加されます)。もしそうなら、このアプローチも非効率的です。

私はこれらの機能の代替を受け入れています。では、UNIXディレクトリツリーを効率的にトラバースするにはどうすればよいでしょうか(その下にあるファイルの合計文字数の線形時間)。

4

5 に答える 5

16

ftw()別名File Tree Walkを試しましたか?

からの抜粋man 3 ftw:

int ftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag), int nopenfd);

ftw() は、指定されたディレクトリ dir から始まるディレクトリ ツリーをたどります。ツリーで見つかった各エントリに対して、エントリのフル パス名、エントリの stat(2) 構造体へのポインタ、および int フラグを指定して fn() を呼び出します。

于 2010-02-22T20:08:15.770 に答える
5

基本的なポイントが 1 つ欠けているようです。ディレクトリ トラバーサルには、ディスクからのデータの読み取りが含まれます。そのデータがキャッシュにある場合でも、キャッシュからプロセスに取得するためにかなりの量のコードを実行することになります。パスも一般的にかなり短く、数百バイトを超えることはほとんどありません。これらを組み合わせると、必要なすべてのパスの文字列を実際の問題なくかなり合理的に構築できることを意味します。文字列の構築に費やされる時間は、ディスクからデータを読み取る時間に比べればまだかなり短いです。つまり、通常は文字列操作に費やす時間を無視して、ディスク使用の最適化だけを行うことができます。

私自身の経験では、ほとんどのディレクトリトラバーサルでは通常、幅優先検索が望ましいということです。現在のディレクトリをトラバースしているので、すべてのサブディレクトリへのフルパスを優先キューのようなものに入れます。現在のディレクトリの走査が終了したら、キューから最初の項目を取得して走査し、キューが空になるまで続けます。これにより一般的にキャッシュの局所性が向上するため、ディスクの読み取りにかかる時間が短縮されます。システム (ディスク速度と CPU 速度、使用可能なメモリの合計など) によって異なりますが、ほとんどの場合、少なくとも深さ優先トラバーサルと同じくらい速く、簡単に 2 倍 (またはその程度) まで速くなります。

于 2010-02-22T16:28:07.963 に答える
4

opendir/ readdir/の使い方closedirは、関数を再帰的にすることです! Dreamincode.netのスニペットをご覧ください。

お役に立てれば。

EDIT R.Sahu に感謝します。リンクの有効期限が切れていますが、waybackアーカイブを介して見つけ、自由にgistに追加しました。それに応じてライセンスを確認し、ソースの元の作成者に帰属することを忘れないでください! :)

于 2010-02-22T16:14:41.160 に答える
2

アプリケーションにとっておそらくやり過ぎですが、これは何億ものファイルを含むディレクトリツリーをトラバースするように設計されたライブラリです。

https://github.com/hpc/libcircle

于 2012-02-09T16:42:00.023 に答える