エクスプローラがディレクトリサイズの一覧を表示してくれないので、Rubyで書きました。
まずは、ひとつのディレクトリのサイズを求めるメソッドです。
def dir_size(dir_path) dir_size = 0 Dir.entries(dir_path).reject{|x|/^\.+$/=~x}.each do |file_name| file_path = File.join([dir_path, file_name]) if File.directory?(file_path) dir_size += dir_size(file_path) else dir_size += File.stat(file_path).size end end return dir_size end
処理の流れ
- 対象ディレクトリの絶対パスを引数とする。
- Dir::entries()でディレクトリ内の要素を取得。(Dir::glob()はカレントディレクトリ云々がややこしいので使用せず。)
- Enumerable#rejectで余分な要素("."と"..")を削除。
- eachで回す。
- 合計値を返す。
具体的には以下のように使用しました。
class Dir
def Dir.size(dir_path)
dir_size = 0
Dir.entries(dir_path).reject{|x|/^\.+$/=~x}.each do |file_name|
file_path = File.join([dir_path, file_name])
if File.directory?(file_path)
dir_size += size(file_path)
else
begin
dir_size += File.stat(file_path).size
rescue Errno::ENOENT
puts "ファイルサイズ取得に失敗しました。ファイル名:#{file_path}"
end
end
end
return dir_size
end
def Dir.content_size_list(dir_path)
unless File.directory?(dir_path)
return [ [dir_path.split("/")[-1], File.stat(dir_path).size] ]
end
list = []
Dir.entries(dir_path).reject{|x|/^\.+$/=~x}.each do |file_name|
file_path = File.join([dir_path, file_name])
if File.directory?(file_path)
list << [file_name, size(file_path)]
else
begin
list << [file_name, File.stat(file_path).size]
rescue Errno::ENOENT
puts "ファイルサイズ取得に失敗しました。ファイル名:#{file_path}"
end
end
end
return list.sort_by{|x| x[1] * -1}
end
end
Dir.content_size_list(ARGV[0] ? ARGV[0] : "./").each do |item|
puts "#{sprintf("%11d", item[1])}: #{item[0]}"
end
せっかくなので、Dirクラスを拡張してみました。例外処理を入れた理由は、ファイル名に特殊な文字(はあと)が入っているファイルがあり、File::stat()した際に例外が発生して処理が止まってしまったためです。そのファイルが読めなくても大勢に影響はないので、適当にログを出して処理をスキップしています。
上のコードをそのままファイルに貼り付けて実行した場合、引数を渡せばそのディレクトリを、引数を渡さなければカレントディレクトリを検索します。ちなみに私は、
ruby (上のコードを書いたファイルの絶対パス) pause
という内容のバッチファイルを作成して使用しています。「pause」はコマンドプロンプトのコマンドです。こうすれば、調べたいディレクトリにバッチファイルを置いて実行するだけでよいので便利です。
.
.
しかし、なんでDirクラスにsize的なメソッドが組み込まれてないんだろう。ルートディレクトリで使ってPCを爆発させる人なんてそうはいないと思うけど・・・他に何か理由がある?