ディレクトリ内のファイルの数を見つけます
質問
Linuxに、最初にディレクトリをリストすることなく、o(1)(ファイルの数とは無関係に)のディレクトリ内のファイルの数を計算する方法はありますか? o(1)でなければ、かなり効率的な方法はありますか?
代替手段を探しています ls | wc -l
.
解決
Readdirはあなたが思うほど高価ではありません。ナックは、各ファイルの統計を避け、(オプションで)LSの出力をソートすることです。
/bin/ls -1U | wc -l
シェル内のエイリアスを回避し、出力を並べ替えず、1ファイルペルラインをリストします(出力をWCに配管するときは厳密に必要ありません)。
元の質問は、「ディレクトリのデータ構造はエントリの数のカウントを保存しますか?」として言い換えることができます。答えはノーです。 Readdir(2)/getDents(2)よりもファイルをカウントする効率的な方法はありません。
他のヒント
特定のディレクトリを統計(統計(1)または統計(2))でリスト全体を通過せずに、特定のディレクトリのサブディレクトリの数を取得し、そのディレクトリへのリンクの数を観察することができます。 N Child Directoriesを備えた特定のディレクトリには、各サブディレクトリの「..」エントリの1つのリンクと「」の2つのリンク、「。」の2つのリンクがあります。指定されたディレクトリの「..」エントリ。
ただし、リスト全体を横断せずに、すべてのファイル(通常のファイルまたはサブディレクトリを問わず)の数を取得することはできません。これは正しいことです。
ただし、「/bin/ls -1U」コマンドはすべてのエントリを取得するわけではありません。それは得られます それだけ ドット(。)文字から始まらないディレクトリエントリ。たとえば、多くのLogin $ Home Directoriesにある「.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.
-format = single-column(-1)オプションは、この場合の「WC」のように、「LS」出力をパイピングするときに「/bin/ls -ua」コマンドでは必要ありません。 「LS」コマンドは、出力が端子ではない場合、単一の列に出力を自動的に書き込みます。
-U
のオプション ls
Posixにはありません、そしてOS Xに ls
GNUとは異なる意味を持っています ls
, 、それはそれが作るということです -t
と -l
変更時間の代わりに作成時間を使用します。 -f
XSI拡張機能としてPOSIXにあります。 GNUのマニュアル ls
説明します -f
なので do not sort, enable -aU, disable -ls --color
と -U
なので do not sort; list entries in directory order
.
Posixは説明しています -f
このような:
各引数をディレクトリとして解釈するように強制し、各スロットにある名前をリストします。このオプションはオフになります
-l
,-t
,-s
, 、 と-r
, 、およびオンにする-a
;順序は、ディレクトリにエントリが表示される順序です。
のようなコマンド ls|wc -l
ファイル名がNewlinesが含まれている場合、間違った結果を与えます。
ZSHでは、このようなことができます。
a=(*(DN));echo ${#a}
D
(glob_dots
)名前が期間から始まるファイルを含む N
(null_glob
)コマンドが空のディレクトリにエラーが発生しないようにします。
またはbashで同じ:
shopt -s dotglob nullglob;a=(*);echo ${#a[@]}
もしも IFS
ASCIIの数字が含まれており、2つの引用符を追加します ${#a[@]}
. 。追加 shopt -u failglob
それを確保するために failglob
絶え間ない。
ポータブルオプションは使用することです find
:
find . ! -name . -prune|grep -c /
grep -c /
置き換えることができます wc -l
ファイル名に新しいラインが含まれていない場合。 ! -name . -prune
ポータブルな代替品です -mindepth 1 -maxdepth 1
.
または、通常、名前が期間から始まるファイルを含めない別の代替手段があります。
set -- *;[ -e "$1" ]&&echo "$#"
ただし、上記のコマンドには、名前が始まるファイルが含まれています。 dotglob
bashまたは glob_dots
ZSHでは設定されています。いつ *
ファイルが一致しないため、コマンドはデフォルト設定でZSHのエラーが発生します。
私はこのコマンドを使用しました。
find * -maxdepth 0 -type d -exec sh -c "echo -n {} ' ' ; ls -lR {} | wc -l" \;
私はあなたがこれをより多く制御できると思います find
:
find <path> -maxdepth 1 -type f -printf "." | wc -c
find -maxdepth 1
ファイルの階層に深く入り込むことはありません。-type f
フィルタリングがファイルのみになります。同様に、使用できます-type d
ディレクトリ用。-printf "."
一致ごとにドットを印刷します。wc -c
文字を数えるので、それはによって作成されたドットをカウントしますprint
...これは、指定されたパスに存在するファイルの数をカウントすることを意味します。
私の知る限り、より良い選択肢はありません。この情報はこの質問に対して外部である可能性があり、Linux(一般的にUNIXの下)のディレクトリの下では、他のファイルのリストが含まれている特別なファイルであることをすでに知っているかもしれません(正確な詳細は特定のファイルに依存することを理解していますシステムですが、これは一般的なアイデアです)。また、リスト全体を横断せずにエントリの総数を見つけるという呼びかけはありません。私が間違っている場合は私を正しくさせてください。
現在のディレクトリ内のすべてのファイルの数については、これを試してください。
ls -lR * | wc -l
LS -1 |を使用しますWC -L