なんか既視感があるなと思ってブログを読み返してみたのですが、過去にバッチファイルを使って似たようなことをしていたのを忘れていました。
バッチファイルでファイル名の先頭に一括で日付を入れてみる | Naokix.net
コマンドプロンプトはWindowsに最初からはいっているので環境構築しなくて済むのですが、バッチファイルのファイル操作はクセがあって使いづらいんですよね。
その点、PHPなら正規表現も使えますし、便利な関数もそろっているのでより柔軟にプログラムを組むことができると思います。WordPressでブログをやっている人ならXAMPPをローカルにインストールしていると思うので、付属のPHPに環境変数のパスを通せば環境を構築する手間も省けます。
動作環境
Windows 7 Professionalの64ビット版です。PHPは前に記事にしたこちらの環境を使ってテストしています。XAMPPを使っているのなら付属のPHPがはいっているので、そちらを流用してもよいかと思います。
WindowsのPHPでHello World! | Naokix.net
targetというフォルダを作成し、次のようなファイルを用意しました。
ファイル名の一覧をコマンドプロンプトに表示する
フォルダ内のファイル名の一覧をコマンドプロンプトに表示するソースコードです。文字コードはUTF-8のBOMなしで保存します。
1 2 3 4 5 6 7 8 9 10 11 | <?php // ディレクトリのパスを記述 $dir = "C:/test/target"; // ディレクトリの存在を確認し、ハンドルを取得 if (is_dir($dir) && $handle = opendir($dir)) { // ループ処理 while (($file = readdir($handle)) !== false) { echo $file."\n"; } } |
3行目はファイル名の一覧を取得したいフォルダのアドレスです。
実行します。
readdir関数はカレントディレクトリである「.」とその親ディレクトリである「..」まで結果として出力します。「.」と「..」を除外して考慮しなければならない場合には次のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php // ディレクトリのパスを記述 $dir = "C:/test/target"; // ディレクトリの存在を確認し、ハンドルを取得 if (is_dir($dir) && $handle = opendir($dir)) { // ループ処理 while (($file = readdir($handle)) !== false) { if ($file === "." or $file === "..") { continue; } echo $file."\n"; } } |
9行目のif文で条件に一致するとcontinue以下をスキップし、while文のループの次を実行します。
ファイル名を一括で変換する
ファイル名の先頭にある「(中華) 」を一括で削除してリネームするソースコードを作成したいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <?php // ディレクトリのパスを記述 $dir = "C:/test/target"; // ディレクトリの存在を確認し、ハンドルを取得 if (is_dir($dir) && $handle = opendir($dir)) { // ループ処理 while (($file = readdir($handle)) !== false) { if ($file === "." or $file === "..") { continue; } // ファイル名の編集 $pattern = '/^\(中華\) /'; $replacement = ''; $newname = preg_replace($pattern, $replacement, $file); // ファイル名の置き換え $oldname = $file; $oldname = $dir."/".$oldname; $newname = $dir."/".$newname; rename($oldname, $newname); } } |
ポイントは16行目のpreg_replace関数と22行目のrename関数です。
preg_replace関数
目的の文字列を$patternを使って検索し、該当する部分を$replacementで置き換えます。今回は$file変数に格納されているファイル名が目的の文字列になります。$patternには正規表現を使うことができます。
「(中華) 」からはじまるファイル名を検索するため、先頭に「^」をつけます。「(」と「)」ですが、サブパターンの開始・終了を意味するメタ文字なので、文字として扱うにはバックスラッシュでエスケープする必要があります。一括削除ですので$replacementは空です。
「うまく動作しない!」というときは、目的の文字列で半角スペースなどを見落としていないか確認してみてください。全角スペースは大丈夫なのですが、半角になると結構やらかします。
rename関数
ネットで検索すると$oldnameや$newnameを相対パスで記述している例を見かけます。ところが、Windowsのローカル環境では絶対パスで指定しないと動作しないようです。3行目の$dir変数を使って20~21行目で絶対パスを作成しています。
動作確認
うまく動作しましたか?
使い勝手を良くするために少し改良します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php // ディレクトリのパスを記述 $dir = "C:/test/target"; // ディレクトリの存在を確認し、ハンドルを取得 if (is_dir($dir) && $handle = opendir($dir)) { // ループ処理 while (($file = readdir($handle)) !== false) { if ($file === "." or $file === "..") { continue; } // ファイル名の編集 $pattern = '/^\(中華\) /'; $replacement = ''; $newname = preg_replace($pattern, $replacement, $file); // ファイル名の置き換え $oldname = $file; echo $oldname." 処理中…"."\n"; $oldname = $dir."/".$oldname; $newname = $dir."/".$newname; rename($oldname, $newname); } echo "おしまい。"."\n"; } |
20行目と26行目を追加しただけです。
「処理中…」ですが、これは現在どのファイルに対して処理を行っているかを確認するためのものです。最近はマシンスペックが上がっているので終了するまでにたいした時間はかかりませんが、処理中なのかバグでプログラムが固まっているのかわからないのはストレスです。地味に作業効率に影響を与えるので、ひと手間をめんどくさがらずマメに記述することをおすすめします。
丸カッコを角カッコに変換する
「(中華) 」だけでなく「(イタリアン) 」の丸カッコも角カッコに変換できるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php // ディレクトリのパスを記述 $dir = "C:/test/target"; // ディレクトリの存在を確認し、ハンドルを取得 if (is_dir($dir) && $handle = opendir($dir)) { // ループ処理 while (($file = readdir($handle)) !== false) { if ($file === "." or $file === "..") { continue; } // ファイル名の編集 $pattern = '/\((.*?)\)/'; $replacement = '[$1]'; $newname = preg_replace($pattern, $replacement, $file); // ファイル名の置き換え $oldname = $file; echo $oldname." 処理中…"."\n"; $oldname = $dir."/".$oldname; $newname = $dir."/".$newname; rename($oldname, $newname); } echo "おしまい。"."\n"; } |
14行目の$patternに「.*?」を指定していますが、これは正規表現の最短一致を適用しています。「.*」にすると最長一致になりますが、これに「なるべく少ない回数だけマッチ」を意味するはてなマークを付けると最短一致になります。
15行目の$replacementでは$1という記号を使っていますが、これは後方参照です。後方参照とは正規表現の機能のひとつで、括弧「()」で括った内容が一時的にバッファに記憶され、その内容を後で使えるというものです。
例えば、「(中華)青椒肉絲(おいしい中華)」という文字列だった場合、$1に「中華」、$2に「おいしい中華」が格納されます。必要であれば$3、$4…と増えていきます。
最後にちゃんと動作するかどうか確認してください。
Comment