画像ファイルの整理(2)

画像ファイルをカテゴリー別に整理する方法もあれば、日付順に整理するという方法もあります。私はデジタルカメラで撮った画像を「年月日」+「通し番号」という形で保存しています。幸いなことに私のデジタルカメラは、直接フロッピーディスクに画像を保存するタイプなので、ファイルのデータにタイプスタンプがそのまま残っているのです。これを利用して、上記のようなファイル名に整理しようというのが、次のスクリプトです。

#!/usr/bin/perl
# mavica.pl
#
# MAVICA の画像ファイルを yymmdd-xxx.jpg 形式にかえる
# 通常の cp コマンドでファイルをコピーすると、ファイルの日付が、アクセス
# した日付になってしまうので、cp -p を用いてフロッピーから作業用ディレク
# トリーにファイルをコピーする
# (例)
# cp -p /mnt/floppy mvc-*.jpg ./
# MTools あるいは MToolsFM でコピーすれば、もとの日付が保存される


# 月の変換テーブル、0月は Dummy
@month_table = qw (Dummy Jan Feb Mar Apr May Jun Jul Aug Sep Nov Dec);

# ファイルの一覧を得る
open DATA, "ls -l --full-time mvc-*.jpg |" or die $!;

$old_name = "";
foreach $line (<DATA>){
    chomp $line;
    # ファイルの一覧からデータを得る
    @data = split /[ ]+/, $line;
    $name = $data[10];
    $year = $data[9];
    $month= $data[6];
    $date = $data[7];

    # 年月日の整形    
    $year = $year - 2000;
    if ($year < 10){
        $p_year = "0$year";
        }
    $i = 1;
    while ($i <= 12){
        if ($month eq $month_table[$i]){
            last;
            }
        $i++;
        }
    if ($i < 10){
        $p_month ="0$i";
        }

    # ファイルの年月日が同じかどうかの判定
    # 同じなら番号をふやす
    $new_name = "$p_year$p_month$date";
    if ($new_name eq $old_name){
        $number++;
        }
    # 同じでなければ 1 からはじめる
    else {
        $number = 1;
        }
    # 番号の整形
    if ($number < 10){
        $p_number = "00$number";
        }
    elsif ($number < 100){
        $p_number = "0$number";
        }
        
    # ファイル名の変換
    system ("mv $name $new_name\-$p_number.jpg");
    # 画面への出力
    print ("$name --> $new_name-$p_number.jpg\n");
    # 比較のため以前のファイル名を保存
    $old_name = $new_name;
    }

ファイルのタイプスタンプを含んだリストを得るには ls -l --full-time というコマンドを使います。すると、

-rw-r--r--    1 penguin   penguin       1515 Wed Feb 27 14:58:34 2002 index.html
などと、表示されます。スペースで区切られたそれぞれのブロックは「属性」、「ファイル数」「所有者」「グループ」「サイズ」「曜日」「月」「日」「時刻」「年」「ファイル名」となっています。ですから、次の式で、「ファイル名」「年」「月」「日」を得ることができます。
    @data = split /[ ]+/, $line;
    $name = $data[10];
    $year = $data[9];
    $month= $data[6];
    $date = $data[7];
各データを分けているのはスペース(' ')ひとつとは限りませんので、正規表現で [ ]+ を使って「スペースが一つ以上の場合」を表しています。split /[ ]+/, $line; の行で $line から得たデータを @data に格納して、それをさらに各変数に代入しています。

$year, $date はそれぞれ二桁の数字に整形しますが、$month は文字なので、これを数字に変換するため

@month_table = qw (Dummy Jan Feb Mar Apr May Jun Jul Aug Sep Nov Dec);
という配列を使いました。次の式で、Jan が 1、Feb が 2 となるようにしています。
    $i = 1;
    while ($i <= 12){
        if ($month eq $month_table[$i]){
            last;
            }
        $i++;
        }
while のループの中の if ($month eq $month_table[$i]){ last; } というのは、データの中に Jan から Dec までのうちのどれかにヒットしたら、そこでループを抜け出すというものです。last がループを抜け出すキーワードです。その時の $i の価はかならず 1 から 12 の間になり、それが何月かを知ることができるというわけです。

さて、写真は、毎日一枚づつ撮るわけではありません。同じ日に何枚も写真をとった場合、020314-001.jpg, 020314-002.jpg, 020314-003.jpg などのように連番をつけるようにします。それには、同じ年月日の名前があった場合、$number という変数をひとつづつふやしていくようにします。それが次の部分です。

    # ファイルの年月日が同じかどうかの判定
    # 同じなら番号をふやす
    $new_name = "$p_year$p_month$date";
    if ($new_name eq $old_name){
        $number++;
        }
    # 同じでなければ 1 からはじめる
    else {
        $number = 1;
        }

ここで使っているテクニックで説明が必要なのは、パイプのオープンでしょう。パイプは、あるプロセスの出力を別のプロセスに引き渡すものです。最初に示した ls -l --full-time mvc-*.jpg というコマンドはそのままなら、スクリーンに出力します。これを ls -l --full-time mvc-*.jpg > list.txt とすれば、ファイルに出力しますので、このファイルを読みこんでデータを取りだしてもいいのですが、

open DATA, "ls -l --full-time mvc-*.jpg |" or die $!;
とすれば、ls -l --full-time mvc-*.jpg の出力は DATA をハンドラーとするバッファに格納され、ファイルと同様、open キーワードで開いたり、foreach $line ( <DATA> ){ .... } などのようにそこから読みこむことができるのです。パイプを上手に使えば、list.txt などといったテンポラリーファイルを作るよりも、はるかにきれいなプログラムを書くことができます。

[前のぺ−ジ] [目次] [次のぺ−ジ]