ファイルの詳細な情報を取得する(stat) - Perl

ファイル容量(サイズ)や更新日など、ファイルの詳しい情報を取得したい。これはPerlが標準で用意している「stat」関数を使用すれば一発である。

サンプル

;#
;#ファイル情報を取得する
;#

#-- ファイル情報を取得 --#
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
      $atime,$mtime,$ctime,$blksize,$blocks)
         = stat('./hoge.txt');

#-- 表示 --#
print join("\n"
    , $dev      # 0: デバイス番号
    , $ino      # 1: iノード番号
    , $mode     # 2: ファイルのモード(種類とパーミション)
    , $nlink    # 3: ハードリンク数
    , $uid      # 4: ユーザID
    , $gid      # 5: グループID
    , $rdev     # 6: デバイス識別子(特殊ファイルのみ)
    , $size     # 7: ファイルのサイズ(バイト単位)
    , $atime    # 8: 最終アクセス時刻
    , $mtime    # 9: 最終変更時刻
    , $ctime    #10: 最終iノード変更時刻
    , $blksize  #11: 標準ブロックサイズ
    , $blocks   #12: ファイルに割り当てられてりるブロック数
);

実行例(FreeBSD)

168710
13945691
33188
1
1126
1000
56414637
4921
1137264426
1136805479
1136805479
16384
12

statではファイル名(ファイルパス)以外にファイルハンドルなども指定できる。普段、よく使用するのは「ファイルのサイズ」「最終変更時刻」程度でしょうか?後は状況によって使ったり使わなかったり。

例えばファイルサイズだけ欲しいといった時には次のように記述します。ファイルサイズと最終更新日など複数の値が欲しい場合はこの応用。配列をスライスするのと同じ要領。(リストのスライス)

$size = (stat($file))[7]
($size, $mtime) = (stat($file))[7,9]

よく配列で全部受けとる人がいますが、そこはお好みで。個人的にはスライスの方が無駄な物が少ない感じがして好きです。ベンチマークを取るとそれほど大きな違いは無いようです。

use Benchmark;

timethese(
    10000,
    {
          'ARRAY' => 'bench_array();'
        , 'SLICE' => 'bench_slice();'
    }
);

sub bench_array{
    my @buff = stat('mixi.jp.txt');
    $a = $buff[7];
}

sub bench_slice{
    my $buff = (stat('mixi.jp.txt'))[7];
    $a = $buff;
}
Benchmark: timing 10000 iterations of ARRAY, SLICE...
ARRAY: 2 wallclock secs ( 0.59 usr + 1.49 sys = 2.08 CPU) @ 4800.77/s (n=10000)
SLICE: 2 wallclock secs ( 0.59 usr + 1.42 sys = 2.01 CPU) @ 4970.18/s (n=10000)