PHP递归删除多目录文件时如何保留指定图片避免误删
现有代码失效原因
你的代码会无差别删除所有内容,核心是两个逻辑错误:
- 自定义的
rrmdir函数是标准的递归强制删目录逻辑,内部没有任何保留指定文件的判断,只要传入目录路径,就会删除目录下所有内容、最后删除目录本身,完全忽略$filesToKeep的规则。 - 外层循环只判断了根目录下的条目名称是否在保留列表中,不会进入子目录做文件名匹配。你根目录下的子文件夹名称显然不会是
partner-profil-480.jpg,所以所有子文件夹都会被直接传入rrmdir整体删除,最终所有内容被清空。
修正后的实现方案
逻辑调整为:递归遍历每个子文件夹,逐个判断文件是否需要保留,非保留文件直接删除,清理完成后可选择删除空目录,不会直接删除整个目录树。
<?php // 定义需要保留的文件名,所有子目录下同名文件都会被保留 $filesToKeep = [ 'partner-profil-480.jpg' ]; /** * 递归清理指定目录 * @param string $dir 待清理目录路径 * @param array $keepFiles 需要保留的文件名列表 */ function cleanDir(string $dir, array $keepFiles): void { if (!is_dir($dir)) return; $entries = scandir($dir); foreach ($entries as $entry) { if ($entry === '.' || $entry === '..') continue; $fullPath = $dir . DIRECTORY_SEPARATOR . $entry; if (is_dir($fullPath)) { // 先递归清理子目录内容 cleanDir($fullPath, $keepFiles); // 子目录清理后为空则删除,不需要删空目录可注释以下3行 if (count(scandir($fullPath)) === 2) { rmdir($fullPath); } } else { // 文件不在保留列表则删除 if (!in_array($entry, $keepFiles)) { unlink($fullPath); } } } } // 遍历根目录下所有子文件夹执行清理 $rootEntries = glob('*'); foreach ($rootEntries as $entry) { if (is_dir($entry)) { cleanDir($entry, $filesToKeep); } // 若需要同时清理根目录下的非保留文件,取消下方注释即可 // else { // if (!in_array($entry, $filesToKeep)) { // unlink($entry); // } // } } ?>
使用说明
- 保留规则匹配文件名,不限制文件所在路径,所有子目录下只要文件名和
$filesToKeep内的条目一致,就不会被删除。 - 代码不会直接删除整个目录,不会出现之前整目录被清空的问题。
- 默认会删除清理后没有任何文件的空目录,如果需要保留空目录,注释掉代码中对应
rmdir($fullPath)的段落即可。 - 默认仅清理子文件夹内的内容,不会修改根目录下的文件;如果需要根目录也执行相同的清理规则,打开代码中对应的注释段即可。
内容的提问来源于stack exchange,提问作者Fenyovari Daniel
相关产品推荐
相关产品推荐

