PHP递归删除函数无法删除名称含大括号的文件夹问题求助
问题原因分析
这个问题我之前碰到过,根源完全出在glob()函数的模式匹配规则上!
你代码里用的glob($dir . '/{,.}[!.,!..]*',GLOB_MARK|GLOB_BRACE),其中{,.}是glob的扩展模式语法——用来同时匹配以点开头(隐藏文件)和非点开头的普通文件。但当目录名本身包含{或}时,glob会把这些字符当成模式的一部分去解析,而不是作为普通文件名的字符处理。
比如目录名是{test},glob在匹配时会尝试把{test}解析成一个模式分组,导致它无法正确匹配到这个目录下的文件和子目录。结果就是这个目录里的内容完全没被删除,最后执行rmdir()时自然会抛出“目录不为空”的异常。
解决方法
推荐直接替换掉glob(),改用更可靠的原生目录遍历函数,完全避开特殊字符的匹配问题:
方案1:使用opendir/readdir遍历目录(最推荐)
public function deleteDownload($dir): void { // 打开目录句柄 $handle = opendir($dir); if (!$handle) { return; } // 遍历目录内的每一项 while (($file = readdir($handle)) !== false) { // 跳过当前目录和上级目录的占位符 if ($file === '.' || $file === '..') { continue; } $fullPath = $dir . DIRECTORY_SEPARATOR . $file; if (is_dir($fullPath)) { // 递归删除子目录 $this->deleteDownload($fullPath); } else { // 删除文件 unlink($fullPath); } } closedir($handle); // 最后删除空目录 rmdir($dir); }
这个方法直接读取目录里的所有原始文件名,完全不受{}、*这类glob特殊字符的影响,兼容性和稳定性都更强。
方案2:转义glob的特殊字符(不推荐,仅作参考)
如果一定要坚持用glob(),需要手动转义文件名里的glob特殊字符(包括{、}、*、?等):
// 转义glob模式中的特殊字符 function escapeGlobPattern($pattern) { $specialChars = ['\\', '*', '?', '[', ']', '{', '}']; return str_replace($specialChars, '\\$0', $pattern); } public function deleteDownload($dir): void { $pattern = escapeGlobPattern($dir) . '/{,.}[!.,!..]*'; foreach(glob($pattern, GLOB_MARK|GLOB_BRACE) as $file) { if(is_dir($file)) { $this->deleteDownload($file); } else { unlink($file); } } rmdir($dir); }
不过这种方式需要覆盖所有glob特殊字符,后续如果遇到其他特殊文件名(比如带*的)还是可能出问题,所以优先选方案1。
内容的提问来源于stack exchange,提问作者user3478148
相关产品推荐
相关产品推荐

