利用 PHP 內建函數組合,可以用極簡潔的代碼實現遞迴刪除目錄內容。本文解析 array_map、glob、array_filter 的組合技巧,並提供更健壯的遞迴刪除函數供生產環境使用。
<?php
// 刪除當前目錄下所有「檔案」
array_map('unlink', array_filter(glob('*'), 'is_file'));
// 刪除當前目錄下所有「空目錄」
array_map('rmdir', glob('*', GLOB_ONLYDIR));
glob('*'):取得當前目錄下所有檔案/目錄名稱陣列。array_filter(..., 'is_file'):過濾出檔案 (非目錄)。array_map('unlink', ...):對每個檔案名稱執行 unlink 刪除。glob('*', GLOB_ONLYDIR):直接只取得目錄名稱。array_map('rmdir', ...):對每個目錄執行 rmdir (僅能刪除空目錄)。rmdir 要求目錄為空。unlink/rmdir 會產生 Warning,且無法捕獲具體失敗項目。<?php
/**
* 遞迴刪除目錄及其所有內容 (檔案 + 子目錄)
* @param string $dir 目標目錄路徑
* @param bool $deleteSelf 是否刪除目標目錄本身 (預設 true)
* @return bool 成功返回 true,失敗拋出異常
*/
function recursiveDelete(string $dir, bool $deleteSelf = true): bool {
if (!is_dir($dir)) {
throw new InvalidArgumentException("$dir 不是有效目錄");
}
$items = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST // 關鍵:先刪除子項,再刪除父目錄
);
foreach ($items as $item) {
$path = $item->getPathname();
if ($item->isFile() || $item->isLink()) {
if (!@unlink($path)) {
throw new RuntimeException("無法刪除檔案: $path");
}
} elseif ($item->isDir()) {
if (!@rmdir($path)) {
throw new RuntimeException("無法刪除目錄: $path");
}
}
}
if ($deleteSelf) {
if (!@rmdir($dir)) {
throw new RuntimeException("無法刪除根目錄: $dir");
}
}
return true;
}
// 使用範例
try {
recursiveDelete('/path/to/cache'); // 刪除 cache 目錄及其所有內容
echo "刪除成功";
} catch (Exception $e) {
echo "刪除失敗: " . $e->getMessage();
}
?>
exec('rm -rf ' . escapeshellarg($dir)) (Linux) 或 exec('rd /s /q ' . escapeshellarg($dir)) (Windows),速度快數個數量級。chmod($path, 0777) 提升權限。「一行代碼」適合快速腳本或單元測試清理,正式專案請使用具備錯誤處理、遞迴支援、日誌記錄的健壯函數。