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

PHP 遞歸刪除目錄及所有檔案:安全、跨平台、支援符號連結

     編輯:PHP 綜合知識

健壯實現

function destroyDir(string $dir, bool $virtual = false): bool {
    $dir = $virtual ? realpath($dir) : $dir;
    if ($dir === false || !is_dir($dir)) return false;
    
    // 統一路徑分隔符,移除尾部斜線
    $dir = rtrim($dir, DIRECTORY_SEPARATOR);
    
    $items = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST // 先刪子項
    );
    
    foreach ($items as $item) {
        $path = $item->getPathname();
        if ($item->isLink() || $item->isFile()) {
            @unlink($path);
        } elseif ($item->isDir()) {
            @rmdir($path);
        }
    }
    
    return @rmdir($dir);
}

傳統遞歸函數(PHP 5.2 相容)

function destroyDir_legacy(string $dir): bool {
    if (!is_dir($dir)) return false;
    $dh = opendir($dir);
    while (($file = readdir($dh)) !== false) {
        if ($file === '.' || $file === '..') continue;
        $path = $dir . DIRECTORY_SEPARATOR . $file;
        if (is_link($path) || is_file($path)) {
            @unlink($path);
        } elseif (is_dir($path)) {
            destroyDir_legacy($path);
        }
    }
    closedir($dh);
    return @rmdir($dir);
}

關鍵安全處理

  1. 符號連結:is_link() 先於 is_dir() 判斷,避免刪除連結目標內容。
  2. CHILD_FIRST:先刪除檔案/子目錄,再刪除父目錄,避免 "Directory not empty"。
  3. 錯誤抑制:@unlink/@rmdir 配合返回值檢查,生產環境建議記錄失敗日誌而非忽略。
  4. 權限檢查:操作前可用 is_writable() 預判,或捕獲 ErrorException。

進階:刪除大目錄非阻塞

function async_destroy_dir(string $dir): void {
    // 寫入任務佇列 (Redis/Database),Worker 進程處理
    $task = ['dir' => $dir, 'created' => time()];
    $redis->lpush('dir_delete_queue', json_encode($task));
}

// Worker 腳本
while (true) {
    $task = $redis->rpop('dir_delete_queue');
    if ($task) {
        destroyDir(json_decode($task, true)['dir']);
    } else {
        sleep(1);
    }
}

測試用例

// 建立測試結構
mkdir('test/a/b/c', 0755, true);
file_put_contents('test/a/file1.txt', '1');
file_put_contents('test/a/b/file2.txt', '2');
symlink('/tmp', 'test/a/link_to_tmp'); // 符號連結

// 執行刪除
var_dump(destroyDir('test')); // true

// 驗證
var_dump(is_dir('test')); // false
var_dump(is_dir('/tmp')); // true (連結目標未受影響)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved