專案遷移、編碼統一或建置腳本中,常需批量更改特定目錄下檔案的副檔名。本文提供一個遞迴函數 foreachDir(),支援指定來源副檔名、目標副檔名,並可選擇處理所有檔案或僅特定副檔名。
/**
* 遞迴批量修改檔案副檔名
* @param string $path 目標目錄路徑 (結尾需帶分隔符)
* @param string $srcExt 來源副檔名,如 'c';'all' 表示所有檔案
* @param string $dstExt 目標副檔名,如 'txt'
* @return void
*/
function foreachDir($path, $srcExt, $dstExt) {
$handle = opendir($path);
if (!$handle) return false;
while (false !== ($file = readdir($handle))) {
if ($file === '.' || $file === '..') continue;
$fullPath = $path . $file;
if (is_dir($fullPath)) {
// 遞迴處理子目錄,補上分隔符
foreachDir($fullPath . DIRECTORY_SEPARATOR, $srcExt, $dstExt);
} else {
$dotPos = strrpos($file, '.');
if ($dotPos === false) continue; // 無副檔名跳過
$fileName = substr($file, 0, $dotPos);
$currentExt = substr($file, $dotPos + 1);
// 判斷是否符合來源副檔名條件
if ($srcExt !== 'all' && strtolower($currentExt) !== strtolower($srcExt)) {
continue;
}
$newName = $path . $fileName . '.' . $dstExt;
if (file_exists($newName)) {
// 目標檔名已存在,可選擇覆蓋、重命名或記錄錯誤
continue;
}
rename($fullPath, $newName);
}
}
closedir($handle);
}
// 使用範例:將 C:\project\src 下所有 .c 檔改為 .txt
foreachDir('C:\\project\\src\\', 'c', 'txt');
$srcExt = 'all' 可一次重命名所有檔案;指定副檔名則精準控制。DIRECTORY_SEPARATOR 常數,相容 Windows/Linux。dry-run 模式:先列出將變更的檔案清單,確認無誤後再執行。RecursiveDirectoryIterator + RecursiveIteratorIterator 替代傳統 opendir/readdir,代碼更現代化。