【PHP】ファイルの拡張子をファイルの中身に合わせて付与するスクリプト

  • 2022年9月9日
  • PHP

 PHPにはファイル署名とMIMEタイプと拡張子を組み合わせた辞書が組み込まれています。この辞書は finfo 関数を用いることでいい感じに使えます。これを利用することで拡張子のないファイルの拡張子を補完できます。これができると拡張子の誤ったファイル群や拡張子なしで保存したファイル群を GUI 上で楽に使うための準備をしやすくなります。

 具体的なスクリプトは次です。

<?php

 foreach(glob('/tgt_dir_path/*') as  $filePath){
    // finfo を使って拡張子を得られるようにすると宣言
    $finfo = finfo_open(FILEINFO_EXTENSION);
    // ファイルの中身からあるべき拡張子を取得
    $ext = $finfo->file($filePath);
    if (! preg_match("/\.{$ext}$/i", $filePath)) {
        // 正規表現のiフラグは大文字小文字を無視するフラグ
        // もしファイル末尾の拡張子がファイルの中身にそぐう拡張子でない場合は
        // 拡張子を付け足したファイルとして名前を変更
        rename($filePath, $filePath.'.'.$ext);
    }
}

 tgt_dir_pathの所に変更したファイル群のあるディレクトリのパスを入れてphp スクリプトファイル名で実行できます。

 finfo はファイル情報機能の中に含まれている機能です。この機能ではファイルのマジックナンバー(ファイルの先頭から始まるバイトにあるファイルの種類固有のバイトコード)からファイルを識別でき、識別結果から色々なことができます。

PHP: Fileinfo – Manual

 このスクリプトではその機能の内の拡張子の取得を用いて、ファイル名末尾に拡張子が見当たらなければ末尾に拡張子を追加、としています。単純なスクリプトですが割とうまく動作します。

 ちなみにマジックナンバーによる識別は完璧ではありません。たまたま先頭のバイトが一致したテキストファイルが最たる例です。SJISエンコードで”公開フラグ”という文字列を先頭に含むテキストファイルがDOS実行ファイルと解釈されるなんて話もあります。

<?php

$finfo = finfo_open();
$txt = finfo_buffer($finfo,mb_convert_encoding("公開フラグ ほげほげ", 'SJIS-win'));
var_dump($txt); // string(34) "DOS executable (COM, 0x8C-variant)"

Online PHP editor | output for 2EVYU#公開フラグがDOS実行ファイル扱いされる例

 PHPのドキュメントも次の様に説明しています。

このモジュールの関数は、ファイル内の特定の位置から
magic バイトシーケンスを見つけることで、
ファイルの content type とエンコーディングを推測します。
これは完全な手法ではありませんが、経験上かなりうまく動作しています。

PHP: はじめに – Manual

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG