最初にディレクトリをリストすることなく、O(1) (ファイル数とは無関係) でディレクトリ内のファイル (つまり、直接の子) の数を計算する方法は Linux にありますか? O(1) でない場合、合理的に効率的な方法はありますか?
に代わるものを探していls | wc -l
ます。
readdir は、あなたが思っているほど高価ではありません。コツは、各ファイルの統計を避けることと、(オプションで) ls の出力をソートすることです。
/bin/ls -1U | wc -l
シェルでエイリアスを回避し、出力をソートせず、1 行に 1 ファイルをリストします (出力を wc にパイプする場合は厳密には必要ありません)。
元の質問は、「ディレクトリのデータ構造にはエントリ数のカウントが格納されていますか?」と言い換えることができ、答えはノーです。readdir(2)/getdents(2) より効率的なファイルのカウント方法はありません。
特定のディレクトリを統計(stat(1)またはstat(2))し、そのディレクトリへのリンクの数を監視することで、リスト全体をトラバースせずに、特定のディレクトリのサブディレクトリの数を取得できます。N個の子ディレクトリを持つ特定のディレクトリのリンク数はN+2で、各サブディレクトリの「..」エントリに1つのリンク、さらに「。」に2つのリンクがあります。指定されたディレクトリの「..」エントリ。
ただし、リスト全体をトラバースしないと、すべてのファイル(通常のファイルまたはサブディレクトリ)の数を取得することはできません。これは正しいことです。
ただし、「/ bin/ls-1U」コマンドはすべてのエントリを取得するわけではありません。ドット(。)文字で始まらないディレクトリエントリのみを取得します。たとえば、多くのログイン$HOMEディレクトリにある「.profile」ファイルはカウントされません。
「/bin/ls-f」コマンドまたは「/bin/ ls-Ua」コマンドのいずれかを使用して、ソートを回避し、すべてのエントリを取得できます。
おそらくあなたの目的のために、「/ bin/ls-f」コマンドまたは「/bin/ls-Ua」コマンドのいずれかが「。」もカウントします。および各ディレクトリにある「..」エントリ。次のように、これら2つのエントリがカウントされないようにするには、カウントから2を引く必要があります。
expr `/bin/ls -f | wc -l` - 2 # Those are back ticks, not single quotes.
この場合の「wc」のように、「ls」出力をパイプする場合、「/ bin/ls-Ua」コマンドで--format=single-column(-1)オプションは必要ありません。「ls」コマンドは、出力が端末でない場合、その出力を単一の列に自動的に書き込みます。
次を使用して、これをより詳細に制御できると思いますfind
。
find <path> -maxdepth 1 -type f -printf "." | wc -c
find -maxdepth 1
ファイルの階層に深く入り込むことはありません。-type f
ファイルだけにフィルタリングできます。-type d
同様に、 for ディレクトリを使用できます。-printf "."
一致ごとにドットを出力します。wc -c
文字をカウントするため、print
... によって作成されたドットをカウントします。これは、指定されたパスに存在するファイルの数をカウントすることを意味します。私はこのコマンドを使用しました..魅力のように機能します..最大深度を変更するためだけに..それはサブディレクトリです
find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;
私の知る限り、これ以上の代替手段はありません。この情報はこの質問のトピックから外れている可能性があり、Linux (一般的には Unix) ではディレクトリは他のファイルのリストを含む単なる特別なファイルであることを既に知っているかもしれません (正確な詳細は特定のファイルに依存することを理解しています)システムですが、これは一般的な考え方です)。また、リスト全体をトラバースせずにエントリの総数を見つけるための呼び出しはありません。私が間違っている場合は、私を正してください。
ls-1を使用する| wc -l