したいこと
特定のファイルの詳細な情報(ファイルのサイズ・タイプ・オーナーのユーザID等)を取得したい。 ※以下、この記事内でファイルという言葉を使う場合は基本的にディレクトリも含んでいます。
File::Statクラス
あるファイルの詳細情報を取得したいときにはFile::stat
クラスを使うと便利です。以下、リファレンスマニュアルによる説明です。
ファイルの情報を格納したオブジェクトのクラス。 FileTest に同名のモジュール関数がある場合はそれと同じ働きをします。ただ、ファイル名を引数に取るかわりに Stat 自身について判定する点が違います。
はい。後半のモジュール関数がどうのこうのというのは正直僕もよくわかっていませんが、今回はそこはそんなに重要じゃない(と思う)ので深くつっこみません。
重要なのはFile::Stat
クラスのオブジェクトはファイルの情報を格納できるということです。(そのまんま)
このクラスのインスタンスメソッドの多くはそのオブジェクトの特定の情報を返してくれるものなので、それらのメソッドを使用して自分の欲しい情報を取得するという使い方になります。
例えば、あるファイルのサイズを知りたい場合はsize
メソッドを用いて以下のような書き方ができます。
file = File.stat("hoge") file.size
stat
メソッドの引数には情報を取得する対象となるファイルのファイル名を渡します。
この場合、変数file
にはhoge
というファイルの各種情報がまとめて格納されていて、その中からファイルサイズの情報をsize
メソッドを使用して取り出しているということになります。
初めてこのクラスを使ったときに個人的にちょっと面白かったのは、File::Stat
クラスのオブジェクトを作成する際にはFile
クラスのstat
メソッドを使用するということ。なるほど。クラス名が::
でつながっている理由が何となくわかった気がします。
実際にはFile::Stat.new
でも作成できますが、そこはかとなくもっちゃりしてませんか?(個人の感想です)
Dir.globと組み合わせる
さて、File::Stat
クラスを使ってファイルの詳細情報をゲットする方法は以上なのですが、それだけだと面白くないので僕が実際にやった具体的な使い方を紹介します。
僕がこのFile::Stat
を使う必要があったのは、カレントディレクトリにある全ファイルの情報を取得したかったからです。
そこで使用したのが、このブログの前々回の記事でご紹介したDir.glob
との組み合わせです。
File.stat
を使用する際の引数は対象となるファイルのファイル名です。そしてDir.glob
はファイル名を取得するためのメソッドです。
もう大体わかると思いますが、要はDir.glob
でファイル名を取得して、それをそのままFile.stat
の引数として渡してしまえば、それらのファイル全ての詳細情報を取得できるということです。
というわけで、僕が実際に書いたのはこんな感じです。
file_names = Dir.glob("*") files = [] file_names.each do |name| files << File.stat(name) end
これでカレントディレクトリの全てのファイル情報が取得できました。(今回は隠しファイルは含めていません。)
流れとしては、
Dir.glob
でファイル名を取得files
という空の配列を用意each
による繰り返し処理で配列files
にFile::Stat
オブジェクトを順番に入れていく
となります。 この配列から任意のファイルの特定の情報を取り出す場合、
files[0].size
のように、インデックスでどのオブジェクトか指定したうえでメソッドを使用します。
トラップ
非常に便利なこのFile::Stat
ですが、1点注意があります。
それはFile::Stat
が格納している情報にはファイル名が含まれていないということ。
これほんとトラップだと思います。
だってよく考えてください。
ここまでの流れからして、
file = File.stat("hoge") file.name
こんなふうにすればhoge
って取得できそうなもんじゃないですか。
でもダメなんです。いくら引数でファイル名を渡していようとそれはそれ、これはこれです(?)
まるで「あなたもうファイル名は知ってるじゃない。私がなんで教えてあげなきゃいけないの?」と意地悪されているような気分になります。
ほんとに謎仕様。
なので、ファイル名は別の変数で用意するか、1つのオブジェクトに入れてしまいたい場合は新しくクラスを定義するのがいいと思います。僕は後者の方法で使用しました。
というわけで、今回はこんな感じです。
記載内容に間違い等があった場合にはこっそり教えていただければ幸いです。 最後までお読みいただきありがとうございました。