首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 批量重命名檔案實作:遞歸遍歷 + 正則替換 + 安全防護

     編輯:PHP 相關知識

PHP 批量重命名檔案實作:遞歸遍歷 + 正則替換 + 安全防護

批量重命名是維運、資料整理常見需求。本文提供一個健壯的 PHP 腳本:遞歸掃描目錄、支援正則/字串替換、乾跑模式預覽、防覆蓋保護、詳細日誌,可直接用於生產環境(建議先備份)。

核心功能

  • 遞歸遍歷:glob() + 遞歸,支援深層目錄。
  • 靈活重命名規則:預設移除檔名中的 [1] 字樣,可自訂正則/回呼。
  • 乾跑模式:$dryRun = true 僅輸出預覽,不實際改名。
  • 防覆蓋:目標檔名已存在時跳過並記錄警告。
  • 詳細日誌:成功/失敗/跳過分類統計,支援輸出 JSON/CSV。

完整腳本

<?php
/**
 * 批量重命名檔案
 * @param string $rootDir 根目錄
 * @param callable $renameFn 檔名轉換函數,接收舊檔名返回新檔名(不含路徑)
 * @param bool $dryRun true=預覽模式,false=實際執行
 * @return array 統計結果
 */
function batchRename(string $rootDir, callable $renameFn, bool $dryRun = true): array {
    $stats = ['renamed' => 0, 'skipped' => 0, 'errors' => 0, 'details' => []];

    // 遞歸收集所有檔案
    $files = [];
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($rootDir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::LEAVES_ONLY
    );
    foreach ($iterator as $file) {
        if ($file->isFile()) $files[] = $file->getPathname();
    }

    foreach ($files as $oldPath) {
        $dir = dirname($oldPath);
        $oldName = basename($oldPath);
        $newName = $renameFn($oldName);

        if ($newName === $oldName) {
            $stats['skipped']++;
            $stats['details'][] = ['old' => $oldPath, 'new' => '', 'status' => 'unchanged'];
            continue;
        }

        $newPath = $dir . DIRECTORY_SEPARATOR . $newName;

        // 防覆蓋檢查
        if (file_exists($newPath)) {
            $stats['errors']++;
            $stats['details'][] = ['old' => $oldPath, 'new' => $newPath, 'status' => 'target_exists'];
            continue;
        }

        if (!$dryRun) {
            if (@rename($oldPath, $newPath)) {
                $stats['renamed']++;
                $stats['details'][] = ['old' => $oldPath, 'new' => $newPath, 'status' => 'ok'];
            } else {
                $stats['errors']++;
                $stats['details'][] = ['old' => $oldPath, 'new' => $newPath, 'status' => 'rename_failed', 'error' => error_get_last()['message'] ?? 'unknown'];
            }
        } else {
            $stats['renamed']++; // 預覽模式計入重命名數
            $stats['details'][] = ['old' => $oldPath, 'new' => $newPath, 'status' => 'dry_run'];
        }
    }
    return $stats;
}

// === 使用範例 ===
$root = __DIR__ . '/uploads'; // 目標目錄

// 規則:移除檔名中的 [1]、[2] 等編號標記
$rule = function(string $name): string {
    return preg_replace('/\[\d+\]/', '', $name);
};

// 1. 先乾跑預覽
$result = batchRename($root, $rule, true);
echo "=== 預覽模式 ===\n";
echo "將重命名: {$result['renamed']} 個\n";
echo "跳過(同名): {$result['skipped']} 個\n";
foreach ($result['details'] as $d) {
    if ($d['status'] === 'dry_run') {
        echo "  {$d['old']}  →  {$d['new']}\n";
    }
}

// 2. 確認無誤後執行
// $result = batchRename($root, $rule, false);
// echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
?>

常見重命名規則範例

需求回呼函數
移除 [數字]fn($n) => preg_replace('/\[\d+\]/', '', $n)
統一小寫fn($n) => strtolower($n)
空格改底線fn($n) => str_replace(' ', '_', $n)
加前綴日期fn($n) => date('Ymd_') . $n
副檔名統一 .jpgfn($n) => preg_replace('/\.[^.]+$/', '.jpg', $n)
複雜正則捕獲重組fn($n) => preg_replace('/(IMG_)(\d+)/', '$1$2_edited', $n)

安全生產清單

  1. 先備份:`rsync -av /data /backup/rename_$(date +%F)`
  2. 乾跑確認:務必先 `$dryRun = true` 檢查輸出。
  3. 權限檢查:腳本執行用戶需有目錄寫入權限。
  4. 大量檔案效能:超過 10 萬檔案建議分批、或用 `find + xargs mv` 系統指令。
  5. 日誌落盤:`file_put_contents('rename_log_' . date('YmdHis') . '.json', json_encode($result, JSON_PRETTY_PRINT))`

延伸閱讀

更多 PHP 檔案系統操作、SPL 迭代器進階、inotify 監控檔案變更、大量檔案處理效能優化、跨平台路徑處理最佳實踐,請參考本站專題系列。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved