ls コマンドで古いファイルも時刻情報がほしい

ファイルの一覧及びその付随情報などを見るのに ls -la コマンドを使う。ところが、古いファイルについては時刻情報が省略され、代わりに年号情報が表示される。例えばこんな感じになる。

$ ls -la
drwxr-xr-x    6 user01   user           4096 Mar  6 18:17 .
drwxr-xr-x   15 bin      bin            4096 Sep 24 19:39 ..
-rw-------    1 user01   user            448 Jul 20 2011  .TTauthority
-rw-------    1 user01   user            845 Jul 20 2011  .Xauthority
drwxr-xr-x   11 user01   user           4096 Jul 20 2011  .dt
-rwxr-xr-x    1 user01   user           3970 Jan 28 2008  .dtprofile
-rwxr-xr-x    1 root     system            0 Sep 29 2008  .history
-rwxr-----    1 user01   user            307 Dec 15 2010  .profile
-rw-------    1 user01   user          15042 Mar  6 23:32 .sh_history
drwxr-xr-x    2 user01   user            256 Mar  6 15:51 aaa

昔のファイルについても更新時間が知りたい。一つや二つであれば Linux なら stat コマンドで、商用UNIXなら istat コマンドでファイルの情報を表示することができる。しかしたくさんのファイルを ls コマンドのように一覧表示させることができない。

ここで、Linux (というか GNU ) の ls なら、--time-style オプションで時間の表示形式を選ぶことができる。例えばこんな感じ。

$ ls -la --time-style=long-iso
drwxr-xr-x    6 user01   user           4096 2013-03-06 18:17 .
drwxr-xr-x   15 bin      bin            4096 2013-09-24 19:39 ..
-rw-------    1 user01   user            448 2011-07-20 13:31 .TTauthority
-rw-------    1 user01   user            845 2011-07-20 13:31 .Xauthority
drwxr-xr-x   11 user01   user           4096 2011-07-20 13:43 .dt
-rwxr-xr-x    1 user01   user           3970 2008-01-28 17:43 .dtprofile
-rwxr-xr-x    1 root     system            0 2008-09-29 17:51 .history
-rwxr-----    1 user01   user            307 2010-12-15 13:37 .profile
-rw-------    1 user01   user          15042 2013-03-06 23:42 .sh_history
drwxr-xr-x    2 user01   user            256 2013-03-06 15:51 aaa

しかし困ったことにプレーンな ls には --time-style オプションが存在しない。さてどうしよう。近頃の OS なら大体とりあえず perl 入ってるし、perl あたりで手を打とう。時刻情報がほしいのでとりあえず時刻とファイル名を表示しよう。

#!/usr/bin/perl
my $dir = './';
$dir = $ARGV[0] if ( $ARGV[0] ne '' ) ;
$dir =~ s/\/$//;
opendir DIR, $dir;
my @files = grep { !m/^(\.|\.\.)$/g } readdir DIR ;
close DIR;
for my $file(@files){
    my ($ss, $mm, $hh, $DD, $MM, $YY, $wday, $yday, $isdst) = localtime( ( stat qq|$dir/$file| )[9] );
    $YY += 1900;
    $MM ++;
    printf "%d-%02d-%02d %02d:%02d:%02d\t%s\n",  $YY, $MM, $DD, $hh, $mm, $ss,$file;
}

でけた。実行してみよう。

$ perl /tmp/stat.pl
2011-07-20 13:31:34     .TTauthority
2011-07-20 13:31:34     .Xauthority
2011-07-20 13:43:04     .dt
2008-01-28 17:43:32     .dtprofile
2008-09-29 17:51:47     .history
2010-12-15 13:37:05     .profile
2013-03-06 23:53:09     .sh_history
2013-03-06 15:51:41     aaa

とりあえずOKいい感じ。目的の日時が得られたので満足です。なに?下層のディレクトリのファイル群についても日時情報がほしい?再帰してほしい?それじゃあファイル情報を取得してる部分だけ切り出して、ディレクトリだった場合に再帰呼び出しすれば行けるね。やってみよう。

#!/usr/bin/perl
my $dir = './';
$dir = $ARGV[0] if ( $ARGV[0] ne '' ) ;
$dir =~ s/\/$//;
&stat1($dir);
exit;
# サブルーチン stat1($dir)
sub stat1{
    my $dir = $_[0];
    opendir DIR, $dir;
    my @files = grep { !m/^(\.|\.\.)$/g } readdir DIR ;
    close DIR;
    for my $file(@files){
        my ($ss, $mm, $hh, $DD, $MM, $YY, $wday, $yday, $isdst) = localtime( ( stat qq|$dir/$file| )[9] );
        $YY += 1900;
        $MM ++;
        my $spath = $dir.'/'.$file;
        printf "%d-%02d-%02d %02d:%02d:%02d\t%s\n",  $YY, $MM, $DD, $hh, $mm, $ss, $spath;
        # ディレクトリの場合再帰呼び出し
        &stat1( $spath ) if ( -d $spath );
    }
}

できあがり。これで日時情報の一覧作り放題です。ところで最近の AIX って perl 5.8 とか標準装備なのな。おかげでいろいろやりやすいです。