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

PHP 遞迴刪除非空目錄與檔案的多種實作方式

     編輯:PHP 相關知識

PHP 內建 rmdir() 僅能刪除空目錄,刪除包含子目錄與檔案的非空目錄需自行實作遞迴邏輯。本文整理四種常見實作模式,涵蓋基礎遞迴、保留目錄僅清空檔案、簡潔版與含權限處理的生產級函式。

方案一:基礎遞迴刪除目錄與檔案

function delDirAndFile($dirName) {
    if ($handle = opendir($dirName)) {
        while (false !== ($item = readdir($handle))) {
            if ($item !== '.' && $item !== '..') {
                $path = "$dirName/$item";
                if (is_dir($path)) {
                    delDirAndFile($path); // 遞迴處理子目錄
                } else {
                    unlink($path);        // 刪除檔案
                }
            }
        }
        closedir($handle);
        rmdir($dirName); // 最後刪除空目錄本身
    }
}

方案二:僅清空目錄下所有檔案(保留目錄結構)

function delFileUnderDir($dirName = '../Smarty/templates/templates_c') {
    if ($handle = opendir($dirName)) {
        while (false !== ($item = readdir($handle))) {
            if ($item !== '.' && $item !== '..') {
                $path = "$dirName/$item";
                if (is_dir($path)) {
                    delFileUnderDir($path); // 遞迴進入子目錄
                } else {
                    unlink($path);          // 僅刪除檔案
                }
            }
        }
        closedir($handle);
    }
}

方案三:簡潔版單一函式

function my_del_dir($directory) {
    if (!is_dir($directory)) {
        exit("The Directory Is Not Exist!");
    }
    $handle = opendir($directory);
    while (($file = readdir($handle)) !== false) {
        if ($file !== '.' && $file !== '..') {
            $path = "$directory/$file";
            is_dir($path) ? my_del_dir($path) : unlink($path);
        }
    }
    // 確認目錄已空後刪除
    if (readdir($handle) === false) {
        closedir($handle);
        rmdir($directory);
    }
}

方案四:生產級函式(含權限處理、錯誤回傳、防循環)

function DeleteDir($sourceDir) {
    $succeed = true;
    if (file_exists($sourceDir)) {
        $objDir = opendir($sourceDir);
        while (false !== ($fileName = readdir($objDir))) {
            if ($fileName !== '.' && $fileName !== '..') {
                $path = "$sourceDir/$fileName";
                // 修正權限避免無法刪除
                chmod($path, 0777);
                if (!is_dir($path)) {
                    if (!unlink($path)) {
                        $succeed = false;
                        break;
                    }
                } else {
                    DeleteDir($path); // 遞迴刪除子目錄
                }
            }
        }
        // 目錄已空則刪除目錄本身
        if (!readdir($objDir)) {
            closedir($objDir);
            if (!rmdir($sourceDir)) {
                $succeed = false;
            }
        }
    }
    return $succeed;
}

// 呼叫範例
DeleteDir("images/abc"); // 刪除 abc 目錄及其所有內容

關鍵注意事項

  • 權限問題: 刪除前建議 chmod($path, 0777) 確保有寫入權限
  • 符號連結: is_dir() 對符號連結會返回 true,遞迴可能進入非預期路徑,生產環境建議加入 is_link() 判斷
  • 錯誤抑制: 避免使用 @ 抑制錯誤,應檢查回傳值並記錄日誌
  • 大量檔案: 遞迴深度過大可能導致堆疊溢位,極大量檔案建議改用迭代器或系統指令 rm -rf(需評估安全性)

現代 PHP 替代方案 (PHP 5.3+)

// 使用 RecursiveDirectoryIterator + RecursiveIteratorIterator
function deleteDirectory($dir) {
    if (!is_dir($dir)) return false;
    $files = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    foreach ($files as $file) {
        $file->isDir() ? rmdir($file->getPathname()) : unlink($file->getPathname());
    }
    return rmdir($dir);
}

方案四的 DeleteDir 函式結合權限修正、布林回傳與中斷機制,適合大多數生產環境;現代專案建議採用 SPL 迭代器寫法,程式碼更簡潔且避免手動遞迴的潛在錯誤。

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