特定ディレクトリ内の大量のファイルの数を知りたい。
数万ファイルあるためか
duコマンドでは遅いので、なるべく速く調べられないか。
ここ最近の Qiita 記事で「bash ファイル数 ディレクトリ内」でググってもタイトルからヒットしなかったので、自分のググラビリティとして。
TL; DR (今北産業)
- 
カレント・ディレクトリ内のファイル数一覧 ls -p -U1 | grep -v / | wc -l
- 
指定したディレクトリ内のファイル数一覧 # /root/data の場合 ls -p -U1 /root/data | grep -v / | wc -l
- 
応用(指定したディレクトリ内のファイル数を表示する) bashサンプル#!/bin/bash list_dir=( '/root/data' '/usr/me/data' '/usr/me/huge/data' ) for path_dir in ${list_dir[@]}; do echo 'Path:' $path_dir ' Files:' $(ls -p -U1 $path_dir | grep -v / | wc -l); done
- オンラインで動作を見る @ paiza.IO
TS; DR
ls -p -U1 | grep -v / | wc -l
- 
ls:一覧表示
- 
-p:ディレクトリの場合はファイル名の末尾に/を追加
- 
-U1:ソートさせない(ファイルが大量なのでソートさせると遅いため)
- 
|grep -v /:パイプから受け取ったディレクトリ(/付きのファイル名)を除外
- 
|wc -l:パイプから受け取った行数をカウント
所感と経緯
機械学習でディレクトリ内に設置した大量のファイルをカウントする必要があったのです。下手に ls や tree しようもんなら、鉄砲玉で帰ってきやしません。
今までカレントディレクトリ内のファイル数をカウントする場合 ls -U1 | wc -l としていました。しかし、サブ・ディレクトリが含まれていると、それらもカウントされていることに気づきました。
確かに、ls -U1 だけを実行するとディレクトリも渡されています。wc コマンドにパイプ渡しする前にディレクトリだけ除外できればいいのですが、ls コマンドに -p オプションを付けてもファイル名の末尾に / と付くだけでした。
悩み始めたのでググってみたところ「grep で / 付きのファイルを -v で除外すればいい」という情報を得て、なんたるちあ。簡単なことでした。
ちなみに ls コマンドの -F オプションを使った方法の情報もあったのですが、遅かったので -p -U1 オプションを使っています。
seq -f "file_%06g" 100000 | xargs touch
time ls -p -U1 | grep -v / | wc -l
time ls -F     | grep -v / | wc -l
# 結果
# real	0m0.060s
# user	0m0.026s
# sys	0m0.047s
# 
# real	0m0.450s
# user	0m0.263s
# sys	0m0.199s
- オンラインで違いを見る @ paiza.IO
参考文献
- List only regular files (but not directories) in current directory @ StackExchange
- ディレクトリ内のファイル数をカウントする @ Qiita
