Because We Love Happy Coding

フリーライターからエンジニア × 講師。発信力だけあり余ってる感じ

ローカルにある画像をPHPで整理する

今日もまたコーディング。だって僕らはHappy Codingが大好きだから。

仕事でNode.jsをガリガリ書いた。パス名とかであれこれ悩みつつ学んだので、何か今のテンションなら行ける!と画像ファイル整理用のスクリプトを書いてみた。

SynologyのNASにはNode.jsがあるのだけどバージョンが4でちょっと古い。8.9.4を入れるのも面倒。

結局、PHPで書いた。

何回かテストしながら書き上げたのがこれ。DropboxのCamera Uploadsに自動で入ってくる画像はファイル名が日付になっているので、それをそのままファイル名にしている。

<?php

foreach(glob('*.jpg') as $filename){
    var_dump($filename);
    $pattern = '/([0-9]{4}).([0-9]{2}).([0-9]{2}) [0-9]{2}.[0-9]{2}.[0-9]{2}.jpg/';
    $replacement = '$1$2$3/';
    $dirname = preg_replace($pattern, $replacement, $filename);
    var_dump($dirname);
    if(!is_dir($dirname)){
        mkdir($dirname,0777,true);
    }
    $newname = preg_replace($pattern, $replacement.$filename, $filename);
    var_dump($newname);
    rename($filename, $newname);
}

動くことは動いたんだけど、Synology の方でどうやらファイル変更がかかるのに時間がかかるみたい。いったんqueに入れて順番に処理していくのかな。1か月分の画像を移動するのにのんびり5分くらいはかかりそう。Dropboxと連携してるせいで遅いのかなー。

しかしDSMのタスクスケジューラに入れておけば夜のうちに勝手にリネームしてくれるわけで、毎晩やるようになればたいした時間もかかるまい。しめしめ。

いくつかポイントなど。

glob

初めはglobだけで正規表現使わずになんとかなるかと思ったんだけど、繰り返しが使えないのが我慢ならぬ。

正規表現置換

最初、"Unknown modifier"というWarningが出て「あれ、何かエスケープし忘れたっけ?」と思ったら違った。

In PHP, a regular expression needs to be enclosed within a pair of delimiters. A delimiter can be any non-alphanumeric, non-backslash, non-whitespace character; /, #, ~ are the most commonly used ones. Note that it is also possible to use bracket style delimiters where the opening and closing brackets are the starting and ending delimiter, i.e. , [pattern_goes_here] etc. are all valid.
--via php - Warning: preg_replace(): Unknown modifier ']' - Stack Overflow

PHPにおける正規表現は「デリミタで囲むこと」とある。/などを使うのが一般的、だそうだ。よくわからんがそうしたら動いた。

後方参照と呼ばれる「検索文字列の一部を置換に使う」のは\1, \2...でいいみたい。$1使う場合もあるみたいだけど、PHPでは\1らしい。

文字クラス外で、バックスラッシュに続いて 1 以上の数値(複数桁可) を記述したものは、パターン中のより前方(すなわち左)にある キャプチャ用サブパターンに対する後方参照 (back reference) です。
--via PHP: 後方参照 - Manual

rename

どうも融通が利かないの。

  1. ディレクトリがあるかどうか確認
  2. なかったらmkdir
  3. renameで移動

という手順を踏む必要があるみたい。このくらい一行でさらっと書けてもよさそうなもんだが、ファイルシステム向きの設計じゃないのかな。

タスクスケジューラ

ディレクトリ名にスペースがあるとパスが切れちゃうみたい。ダブルクォーテーションで囲むとよさげ。

コマンドラインからだとどちらも動く。

php "/volume1/homes/{usr_name}/hoge fuga/photo.php"
php "/var/services/homes/{usr_name}/hoge fuga/photo.php"

それでもPermissionがどうのこうのいうので、sudo使ってやった。
タスクスケジューラではrootユーザーにしたらいいのかなー。実行しても反応が薄いので、動いているのかどうかよくわからん……。

結局

結局、Synologyのタスクスケジューラが難物で、自動実行してくれず、週に一度くらい、MacのコンソールからPHPに渡して実行している。幸い、Finder代替として使用しているPathFinderは右クリックからコンソールを起動できるので、手作業よりは、だいぶ楽になった。