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