この質問は次の質問によく似ています。
実際、私の試みはすべてこの質問に記載されています。
違いは、私のリストに多数のファイル(1M +)があり、これらの試みがそれほど多くの項目では機能しないようです。
の場合、stat
次のdu
エラーが発生します。
-bash: /usr/bin/stat: Argument list too long
-bash: /usr/bin/du: Argument list too long
Perlソリューションはうまくいくようですが、非常に遅く、リスト全体を処理できるかどうか、競合が発生するかどうかはわかりません。
元のファイルを複数の部分に分割し、その部分の合計を合計しない解決策はありますか?
答え1
または(シンボリックリンクを確認したい場合)、システムコールを/some/dir/file
使用して実行されたファイルサイズを確認するには、システムに次のものが必要です。lstat()
stat()
- inodeを照会し、それに対する読み取りおよび検索アクセス権があることを確認し、
/
ディレクトリの内容がどこにあるかに関する情報を取得します。/
- 内容を読み、その中の項目を
/
見つけます(inode番号を入手してください)。some
- forと同様に、inodeで権限などを
/
確認してください。/some
- for
/some/dir
とforを繰り返します。/some/dir/file
/some/dir/file
検索された inode のサイズ属性
一部のパスコンポーネントがシンボリックリンクの場合は、そのコンポーネントも解決する必要があります。
ACLや他のセキュリティコンテキストが関連している場合、検索はより複雑になります。照会を実行すると、root
これらの一部がバイパスされ、プロセスが速くなる可能性があります。
したがって、stat()
(またはファイルを見つけるためのシステムコール)、高価な作業になる可能性があります。特に、すべてのデータ(inodeとディレクトリの内容とセキュリティ属性)がメモリにキャッシュされておらず、システム内のさまざまな場所から取得する必要がある場合は、これがさらに重要です。検索するハードディスク。
ディレクトリの内容がキャッシュされていても、インデックス付けされていない大きなディレクトリでファイルを見つけるためのコストはかなり高くなる可能性があります。
便利な方法は、同じディレクトリにあるファイルが互いに隣にリストされるようにファイルのリストをソートし、特定のファイルが見つかったときにデータがキャッシュされる可能性を最大化することです。
また、あまりにも多くのコマンドを実行したり、不要な追加操作を実行したりしないようにしたい場合があります。
だから:
LC_ALL=C sort file | perl -lne '$s += -s} END {print $s'
(などroot
)は、おそらく簡単に達成できる最速の速度に近いです。
stat()
(ここで、システムコールはシンボリックリンクの場合に指すファイルのサイズを考慮するために使用されます。)
これをさらに最適化する方法があります。たとえば、次のような場合があります。
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file1
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file2
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file3
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs/file4
open()
/some/very/very/deep/dir/structure/with/many/levels/of/subdirs
毎回すべてのdirコンポーネントを照会する必要がないように、そのディレクトリに基づいてfstatat()
for file1
、...一度実行する方が速いかもしれませんが、file2
この最適化を実装するのは簡単ではありません(それほど簡単でも難しくもありません)。 。
データによっては、いくつかの特定の最適化が可能な場合があります。たとえば、ファイルが複数回リストされている場合は、2番目と追加のstat()
ファイルを最適化できます。/foo
それがシンボリックリンクであり、以下に何千もの同じファイルがある場合は、/bar
実際にはvsと同じファイルであることがわかったら、いくつかを最適化できます。/foo
/bar
stat()
/foo/file
/foo/./file
/bar/../foo/file