各ディレクトリのファイル数を数える方法は?


104

私はすべてのディレクトリをリストすることができます

find ./ -type d

次のコマンドを使用して、各ディレクトリの内容を一覧表示し、各ディレクトリ内のファイル数をカウントしようとしました

find ./ -type d | xargs ls -l | wc -l

しかし、これはによって返された行の総数を合計した

find ./ -type d | xargs ls -l

各ディレクトリのファイル数を数える方法はありますか?


直下の各サブディレクトリにあるファイルの数を数える方法を探しています./か?
Tuxdude 2013年

5
これはトピック外の質問ですか?? 理由のある投票者のコメントを見てほしい!これが主題外の場合、これはどこに属していますか?スーパーユーザー?私はそうは思いません..
InfantPro'Aravind '

6
シェルスクリプト、バッチスクリプトはプログラミングの範囲内です!
InfantPro'Aravind '

Pythonicソリューションを投稿しようとしていたところ、質問が終了していることに気付きました。
anatly techtonik 2013年

それを再開するために投票した。多くの状況で役立つ可能性のある他の回答があるかもしれません(スクリプトプログラミングなど、これが私がこの質問に至った理由です)。
lepe 2014

回答:


110

あなたがGNU findを持っていると仮定すると、ディレクトリを見つけさせ、残りをbashにさせましょう:

find . -type d -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

2
上記とは少し異なるバージョンなので、(ヒント:名前でソートされ、csvで)x in find . -maxdepth 1 -type d | sort; y =を実行しfind $x | wc -lます。echo $ x、$ y; 完了
pcarvalho 2013年

5
偉大な者!それを単一の行に入れる(シェルで直接使用するのにfind . -type d -print0 | while read -d '' -r dir; do files=("$dir"/*); printf "%5d files in directory %s\n" "${#files[@]}" "$dir"; done
快適です

13
各サブディレクトリ内のすべてのファイルの数(再帰的に数える)を取得する必要がありました。この変更は、あなたのことを示します: find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find $dir -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done
OmidS

1
@Kory以下はそれを行います:find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done | sort -rn -k1
OmidS

1
@OmidS素晴らしいonelinerですが$dir、空白を含むディレクトリ名を正しく処理するには、最初のコメントの引用符で囲む必要があります。:find . -maxdepth 1 -type d -print0 | while read -d '' -r dir; do num=$(find "$dir" -ls | wc -l); printf "%5d files in directory %s\n" "$num" "$dir"; done
Radek Daniluk

183

これにより、現在のディレクトリレベルのディレクトリごとのファイル数が出力されます。

du -a | cut -d/ -f2 | sort | uniq -c | sort -nr

9
トップレベルのディレクトリにあるファイルの数を再帰的に一覧表示したい場合は、これが最善の(そして最もエレガントな)ソリューションです。
itoctopus

13
これには2つの問題があります。ディレクトリあたり1つのファイルを実際よりも多くカウントし、現在のディレクトリのサイズを「1 サイズ」として含む無駄な行を提供します。どちらもで修正できますdu -a | sed '/.*\.\/.*\/.*/!d' | cut -d/ -f2 | sort | uniq -c。追加| sort -nrして、ディレクトリ名の代わりにカウントでソートします。
デザート

3
これはOSXでも機能することを指摘しておきます。(LinuxのアドバイスをOSXシェルにコピーアンドペーストするだけでは、通常は機能しません。)
ピストス2018

2
du -aで不要なサイズを取得します。より良い方法は、findコマンドを使用することです。しかし、主な考え方はまったく同じです:)
Znik

5
見つける。-type f | カット-d / -f2 | 並べ替え| uniq -c | sort -nr#デザートで言及された問題を修正
jcomeau_ictx

28
find . -type f | cut -d/ -f2 | sort | uniq -c
  • find. -type f タイプファイルのすべてのアイテムを検索するには
  • cut -d/ -f2 特定のフォルダを切り取る
  • sort フォルダ名のリストをソートする
  • uniq -c 各フォルダ名がカウントされた回数を返す

8
トップレベルのディレクトリの概要が表示されるので、これは受け入れられた回答よりもはるかに優れています。
Jason Floyd

3
これは受け入れられる答えになるはずです。シンプルでわかりやすい。
xssChauhan

1
受け入れられるべき最良の答えはこれです。
loretoparisi

1
シンプルでエレガント、そして私のニーズにぴったりです。
RichR

完璧です。また、フィールド指定子をフィールド指定子のリストで置き換えることにより、サブディレクトリを数えるように拡張できます。例:find . -type f | cut -d/ -f2,3 | sort | uniq -c
藻類

15

すべてのファイルを検索し、ファイル名を削除して、各ファイルのディレクトリ名のみを含む行を残してから、各ディレクトリが表示される回数を数えることができます。

find . -type f |
sed 's%/[^/]*$%%' |
sort |
uniq -c

これで唯一の落とし穴は、改行文字を含むファイル名またはディレクトリ名がある場合です。ファイル名やディレクトリ名の改行について本当に心配する必要がある場合は、改行を見つけて修正し、改行が含まれないようにすることをお勧めします(そして、方法の誤りについて有罪を説得します)。


現在のディレクトリの各サブディレクトリにあるファイルの数に興味があり、サブディレクトリにあるファイルと直接のサブディレクトリにあるファイルをカウントしている場合は、sedコマンドを印刷のみに適用しますトップレベルのディレクトリ:

find . -type f |
sed -e 's%^\(\./[^/]*/\).*$%\1%' -e 's%^\.\/[^/]*$%./%' |
sort |
uniq -c

最初のパターンは、名前の先頭、ドット、スラッシュ、次のスラッシュまでの名前とスラッシュをキャプチャし、行を最初の部分だけに置き換えます。

./dir1/dir2/file1

に置き換えられます

./dir1/

2番目の置換では、ファイルを現在のディレクトリに直接キャプチャします。末尾にスラッシュはなく、それらはに置き換えられ./ます。ソートとカウントは、名前の数だけに作用します。


1
これはファイルを含まないディレクトリ名を出力しません。これが必要かどうかはわかりません。
オースティンフィリップス

確かにそうではありません。空のディレクトリ名がの出力に表示されることも保証されていないため、これを修正するのは特に簡単ではありませんfind。ファイルdir1/dir2/dir3/file1があるdir1/dir2が、サブディレクトリしか含まれていない(プレーンファイルがない)場合は、その存在を推測できます。ただし、dir1/dir4ファイルがない場合、その名前は表示されません。
ジョナサンレフラー2013年

現在のディレクトリのサブディレクトリを表示したいだけの場合に非常に役立つ回答です。
xixixao 2014年

よろしくお願いします。これが投稿されてから3年後、私はフォルダーごとに第2レベルのフォルダーを数えることを考えていました。あなたの投稿は、私にsedをいじりの潜在的に多くの時間を保存見つけ、誰が他に何を知っている
コルビン

13

これは1つの方法ですが、おそらく最も効率的ではありません。

find -type d -print0 | xargs -0 -n1 bash -c 'echo -n "$1:"; ls -1 "$1" | wc -l' --

このような出力を提供します。ディレクトリ名の後に、そのディレクトリのエントリ数が続きます。出力カウントには、希望と異なるディレクトリエントリも含まれることに注意してください。

./c/fa/l:0
./a:4
./a/c:0
./a/a:1
./a/a/b:0

3つのコマンドを(実行するために非常に高価なようでbashlswcで見つかった各ディレクトリのため)find
ジョナサンレフラー2013年

@JonathanLeffler同意したので、私の答えの最初の行。あなたのソリューションは優れています。
オースティンフィリップス

これは私が探しているものです、最後に「-」は何ですか?
一度

1
@once--xargsによって生成されるbashコマンドに属します。からman bashA -- signals the end of options and disables further option processing。この場合、検索の一部として見つかった名前の誤ったファイルがbashの引数処理の一部になるのを防ぎます。
オースティンフィリップス

8

他のすべての人のソリューションには、いくつかの欠点があります。

find -type d -readable -exec sh -c 'printf "%s " "$1"; ls -1UA "$1" | wc -l' sh {} ';'

説明:

  • -type d:ディレクトリに興味があります。
  • -readable:それらのファイルを一覧表示できる場合にのみ必要です。findがさらにディレクトリを検索しようとするとエラーが発生することに注意してください-exec。ただし、これによりそれらを呼び出すことができなくなります。
  • -exec sh -c BLAH sh {} ';':各ディレクトリのために、と、このスクリプトフラグメントを実行する$0に設定shし、$1ファイル名に設定します。
  • printf "%s " "$1":移植可能かつ最小限にディレクトリ名を出力し、その後に改行ではなくスペースのみを出力します。
  • ls -1UA:リストファイルの1行に1つは、ディレクトリの順に(パイプを失速回避するため)、除くだけの特別なディレクトリ...
  • wc -l:行を数える

1
ファイルカウントを行の最初に表示し、それらでソートするための変更:find -type d -readable -exec sh -c 'ls -1UA "$1" | wc -l | tr -d "\n" ; printf "\t%s\n" "$1" ' sh {} ';' | sort -n
Evgeni Sergeev

シェルを何度も実行しますが、遅く、リソースを高度に利用します。
Znik

6

のわずかに変更されたバージョン (実行する必要があり、決して使用されないファイルサイズ関連のオーバーヘッドを除外するため)のfind代わりに使用するセバスチャンの回答の:dudu

 find ./ -mindepth 2 -type f | cut -d/ -f2 | sort | uniq -c | sort -nr

-mindepth 2パラメータは、現在のディレクトリ内のファイルを除外するために使用されます。削除すると、次のような一連の行が表示されます。

  234 dir1
  123 dir2
    1 file1
    1 file2
    1 file3
      ...
    1 fileN

(- duベースのバリアントと同じように)

現在のディレクトリのファイルもカウントする必要がある場合は、次の拡張バージョンを使用します。

{ find ./ -mindepth 2 -type f | cut -d/ -f2 | sort && find ./ -maxdepth 1 -type f | cut -d/ -f1; } | uniq -c | sort -nr

出力は次のようになります。

  234 dir1
  123 dir2
   42 .

5

これは、findの代わりにlsをループして行うこともできます。

for f in */; do echo "$f -> $(ls $f | wc -l)"; done

説明:

for f in */; -すべてのディレクトリをループします

do echo "$f -> -各ディレクトリ名を出力します

$(ls $f | wc -l) -このディレクトリに対してlsを呼び出し、行を数える


1
ディレクトリ名に空白が含まれている場合、これは正しく機能しません。
Xylol 2017

試してくださいfor f ./* ; do echo $f $(ls "$f" | wc -l); done
4ndt3s

3

これにより、ディレクトリ名に続いてディレクトリ内のファイル数が返されます。

findfiles() {
    echo "$1" $(find "$1" -maxdepth 1 -type f | wc -l)
}

export -f findfiles

find ./ -type d -exec bash -c 'findfiles "$0"' {} \;

出力例:

./ 6
./foo 1
./foo/bar 2
./foo/bar/bazzz 0
./foo/bar/baz 4
./src 4

の引数は、bashを明示的に呼び出さない限りbash関数の実行を許可せず、現在のスコープで定義されている関数を新しいシェルに明示的にエクスポートするexport -f必要があるため、必須です。-execfind


これは過度に複雑に思えます。また、ディレクトリ階層の累積カウントを与えるようにも見え./dir1/dir2/dir3ます(dir1ファイルをdir1/dir2/dir3個別にカウントするのではなく、ファイルとそのサブディレクトリを一緒にカウントするのではなくdir1/dir2、両方で個別にカウントします/dir1)。
ジョナサンレフラー2013年

それが作者が望んでいたことだと私は理解しました。そうでない場合は、回答が質問に関連しないことに同意します。
Tuxdude 2013年

1
@JonathanLeffler-さて、もう一度質問を読んで、私はあなたが正しいと気づきました-それに応じて答えを修正しました。
Tuxdude 2013年

2

@glenn jackmanの回答@pcarvalhoの回答を組み合わせました(コメントリストでは、文字 ' ` '(バックティック)の余分なスタイル制御機能があるため、pcarvalhoの回答に問題があります)。

私のスクリプトは、としてaugumentとソートディレクトリのリストとしてパスを受け入れることができls -l、また、それがハンドル「ファイル名にスペース」の問題をすることができます

#!/bin/bash
OLD_IFS="$IFS"
IFS=$'\n'
for dir in $(find $1 -maxdepth 1 -type d | sort); 
do
    files=("$dir"/*)
    printf "%5d,%s\n" "${#files[@]}" "$dir"
done
FS="$OLD_IFS"

Stackoverflowでの私の最初の答え、そしてそれが誰かを助けることを願っています^ _ ^


1

見つける。-type f -printf '%h \ n' | 並べ替え| uniq -c

たとえば:

  5 .
  4 ./aln
  5 ./aln/iq
  4 ./bs
  4 ./ft
  6 ./hot

0

ここでは他のいくつかを試してみましたが、ファイルだけが必要なときに、ファイル数にサブフォルダーが含まれていました。これ./folder/path<tab>nnnは、現在のフォルダーの各サブフォルダーについて、サブフォルダーを含まないファイル数で印刷します。

for d in `find . -type d -print` 
do 
  echo -e "$d\t$(find $d -maxdepth 1 -type f -print | wc -l)"
done

0

特定のタイプのファイルを再帰的に見つける簡単な方法。この場合、現在のディレクトリのすべてのフォルダの.jpgファイル:

find . -name *.jpg -print | wc -l


0

超高速miracleコマンド。ファイルを再帰的に走査して、ディレクトリ内の画像の数をカウントし、画像の拡張子ごとに出力を整理します。

find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'

クレジット:https : //unix.stackexchange.com/a/386135/354980


0

これは、ディレクトリ構造を参照して詳細な結果を提供するもう1つの方法です。

find . -type d  | awk '{print "echo -n \""$0"  \";ls -l "$0" | grep -v total | wc -l" }' | sh 

0

node_modules分析したディレクトリ内のすべてのディレクトリを除外するためにスクリプトを編集しました。

これを使用して、ファイルのプロジェクト数がFile Watcherが処理できる最大数を超えているかどうかを確認できます。

find . -type d ! -path "*node_modules*" -print0 | while read -d '' -r dir; do
    files=("$dir"/*)
    printf "%5d files in directory %s\n" "${#files[@]}" "$dir"
done

システムが監視できる最大ファイルを確認するには:

cat /proc/sys/fs/inotify/max_user_watches

node_modules 遅いシステムではIDE /エディターで除外されたパスにフォルダーを追加する必要があり、他のファイル数が最大数を超えることは理想的ではありません(ただし、変更可能です)。


-1

これにより、全体の数がわかります。

for file in */; do echo "$file -> $(ls $file | wc -l)"; done | cut -d ' ' -f 3| py --ji -l 'numpy.sum(l)'

いいえ、それはしません。1つのレベルのサブディレクトリのみを考慮します。
Kusalananda
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.