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