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(需評估安全性)// 使用 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 迭代器寫法,程式碼更簡潔且避免手動遞迴的潛在錯誤。