【PHP】プレーンな PHP でファイル、ディレクトリ、中身の有無を問わず削除する関数

  • 2021年3月26日
  • 2022年10月10日
  • PHP

 PHP のファイル削除、ディレクトリ削除は少々処理が手間です。具体的に何が手間かというと、削除対象がファイルかディレクトリかで用いる関数が unlink か rmdir か変わり、更にディレクトリを削除する時はディレクトリの中身が空である必要があります。Windows でゴミ箱に捨てるぐらい楽にやれるとうれしいです。
 そういった条件分岐や前処理を 1 関数にまとめた関数が次です。

<?php

/**
 * ファイル、ディレクトリ、中身の有無を問わず削除
 * @param  string  $path 削除対象のフルパス
 */
function remove(string $path): void
{
    if(!file_exists($path)){
        // 存在しない対象が指定されれば、削除済みということで return
        return;
    }

    if(is_file($path)) {
        // ファイルである(ファイルシステムの階層構造の末端である)ならば削除して return
        unlink($path);
        return;
    }

    // ディレクトリであるならば内部を見て一つ一つ適切に処理
    if($handle = opendir($path)) {
        // ディレクトリの中全てを一つ一つ読み進める
        while(false !== ($item = readdir($handle))) {
            if($item === '.' || $item === '..') {
                // カレントディレクトリか親ディレクトリならば何もせずにループ続行
                continue;
            }
            // カレントディレクトリでも親ディレクトリでもないのならば再帰呼び出し
            // 再帰先ではディレクトリならばもっと掘り進めて、ファイルならば削除する
            remove($path . DIRECTORY_SEPARATOR . $item);
        }
        // 読み終わったらディレクトリハンドルを閉じる
        closedir($handle);
        // 既に中を全て削除済みである現参照ディレクトリを削除する
        rmdir($path);
    }
}
// 使用例
// 決め打ちで削除
remove(__DIR__ . DIRECTORY_SEPARATOR . 'app/Models/Eloquents/User.php');

// コマンドライン引数から削除
for($i = 1; $i < $argc; $i++){
    // 0 番にはこのPHPスクリプトファイルが格納されているためスキップ
    remove(__DIR__ . DIRECTORY_SEPARATOR . $argv[$i]);
}

 フレームワークやライブラリを読み込む必要はありません。これだけで動作します。何かしらの helper 関数、ファイルクラスに組み込むのも便利です。
 よほどのことがなければファイルシステム操作機能付きのライブラリやフレームワークにはこれと同様の機能が備わっています。それらを使わず平の PHP を使う利点はその場で準備不要のスクリプトとして扱いやす点にあります。上述のスクリプトならば docker や git から読み取った削除対象ファイルの情報を使って、そういったものが使えない別環境のファイルを削除する時などによく出番があります。

 余談。SPL にディレクトリ内を再帰で探索する機能があり、これを使うとより短く書けました。
ディレクトリ内のファイルの消去 – Qiita
PHP: RecursiveDirectoryIterator – Manual

function remove(string $path): void
{
    if(!file_exists($path)){
        // 存在しない対象が指定されれば、削除済みということで return
        return;
    }
	$itr = new RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST);
	foreach ($itr as $file) {
	    $file->isDir() ? rmdir($file->getPathname()) : unlink($file->getPathname());
	}
}
>株式会社シーポイントラボ

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

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

CTR IMG