【发布时间】:2010-12-11 20:17:20
【问题描述】:
我正在尝试删除带有rmdir 的目录,但我收到了“目录不是空的”消息,因为其中仍有文件。
我可以使用什么函数来删除包含所有文件的目录?
【问题讨论】:
我正在尝试删除带有rmdir 的目录,但我收到了“目录不是空的”消息,因为其中仍有文件。
我可以使用什么函数来删除包含所有文件的目录?
【问题讨论】:
没有内置函数可以执行此操作,但请参阅http://us3.php.net/rmdir 底部的 cmets。许多评论者发布了他们自己的递归目录删除功能。您可以从中挑选。
function deleteDirectory($dir) {
if (!file_exists($dir)) {
return true;
}
if (!is_dir($dir)) {
return unlink($dir);
}
foreach (scandir($dir) as $item) {
if ($item == '.' || $item == '..') {
continue;
}
if (!deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
return false;
}
}
return rmdir($dir);
}
如果你想保持简单,你可以调用rm -rf。这确实使您的脚本仅适用于 UNIX,因此请注意这一点。如果你走那条路,我会尝试类似:
function deleteDirectory($dir) {
system('rm -rf -- ' . escapeshellarg($dir), $retval);
return $retval == 0; // UNIX commands return zero on success
}
【讨论】:
/..
function rrmdir($dir)
{
if (is_dir($dir))
{
$objects = scandir($dir);
foreach ($objects as $object)
{
if ($object != '.' && $object != '..')
{
if (filetype($dir.'/'.$object) == 'dir') {rrmdir($dir.'/'.$object);}
else {unlink($dir.'/'.$object);}
}
}
reset($objects);
rmdir($dir);
}
}
【讨论】:
您总是可以尝试使用系统命令。
如果在 linux 上使用:rm -rf /dir
如果在 Windows 上使用:rd c:\dir /S /Q
在上面的帖子 (John Kugelman) 中,我认为 PHP 解析器会优化 foreach 中的 scandir,但在 foreach 条件语句中使用 scandir 对我来说似乎是错误的。
您也可以只执行两个array_shift 命令来删除. 和..,而不是总是检查循环。
【讨论】:
想不出比这更简单、更有效的方法
function removeDir($dirname) {
if (is_dir($dirname)) {
$dir = new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST) as $object) {
if ($object->isFile()) {
unlink($object);
} elseif($object->isDir()) {
rmdir($object);
} else {
throw new Exception('Unknown object type: '. $object->getFileName());
}
}
rmdir($dirname); // Now remove myfolder
} else {
throw new Exception('This is not a directory');
}
}
removeDir('./myfolder');
【讨论】:
这是我用的:
function emptyDir($dir) {
if (is_dir($dir)) {
$scn = scandir($dir);
foreach ($scn as $files) {
if ($files !== '.') {
if ($files !== '..') {
if (!is_dir($dir . '/' . $files)) {
unlink($dir . '/' . $files);
} else {
emptyDir($dir . '/' . $files);
rmdir($dir . '/' . $files);
}
}
}
}
}
}
$dir = 'link/to/your/dir';
emptyDir($dir);
rmdir($dir);
【讨论】:
我的案例有很多棘手的目录(包含特殊字符、深度嵌套等的名称)和隐藏文件,这些文件在其他建议的解决方案中会产生“目录非空”错误。由于仅 Unix 的解决方案是不可接受的,因此我进行了测试,直到找到以下解决方案(在我的情况下效果很好):
function removeDirectory($path) {
// The preg_replace is necessary in order to traverse certain types of folder paths (such as /dir/[[dir2]]/dir3.abc#/)
// The {,.}* with GLOB_BRACE is necessary to pull all hidden files (have to remove or get "Directory not empty" errors)
$files = glob(preg_replace('/(\*|\?|\[)/', '[$1]', $path).'/{,.}*', GLOB_BRACE);
foreach ($files as $file) {
if ($file == $path.'/.' || $file == $path.'/..') { continue; } // skip special dir entries
is_dir($file) ? removeDirectory($file) : unlink($file);
}
rmdir($path);
return;
}
【讨论】:
来自http://php.net/manual/en/function.rmdir.php#91797
Glob 函数不返回隐藏文件,因此 scandir 在尝试递归删除树时可能更有用。
<?php
public static function delTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}
?>
【讨论】:
试试以下方便的功能:
/**
* Removes directory and its contents
*
* @param string $path Path to the directory.
*/
function _delete_dir($path) {
if (!is_dir($path)) {
throw new InvalidArgumentException("$path must be a directory");
}
if (substr($path, strlen($path) - 1, 1) != DIRECTORY_SEPARATOR) {
$path .= DIRECTORY_SEPARATOR;
}
$files = glob($path . '*', GLOB_MARK);
foreach ($files as $file) {
if (is_dir($file)) {
_delete_dir($file);
} else {
unlink($file);
}
}
rmdir($path);
}
【讨论】:
我不是来删除文件夹的,因为 PHP 告诉我它不是空的。但它是。 Naman 的功能是完成我的好解决方案。所以这就是我使用的:
function emptyDir($dir) {
if (is_dir($dir)) {
$scn = scandir($dir);
foreach ($scn as $files) {
if ($files !== '.') {
if ($files !== '..') {
if (!is_dir($dir . '/' . $files)) {
unlink($dir . '/' . $files);
} else {
emptyDir($dir . '/' . $files);
rmdir($dir . '/' . $files);
}
}
}
}
}
}
function deleteDir($dir) {
foreach(glob($dir . '/' . '*') as $file) {
if(is_dir($file)){
deleteDir($file);
} else {
unlink($file);
}
}
emptyDir($dir);
rmdir($dir);
}
所以,要删除一个目录并递归地删除它的内容:
deleteDir($dir);
【讨论】:
使用此功能,您将能够删除任何文件或文件夹
function deleteDir($dirPath)
{
if (!is_dir($dirPath)) {
if (file_exists($dirPath) !== false) {
unlink($dirPath);
}
return;
}
if ($dirPath[strlen($dirPath) - 1] != '/') {
$dirPath .= '/';
}
$files = glob($dirPath . '*', GLOB_MARK);
foreach ($files as $file) {
if (is_dir($file)) {
deleteDir($file);
} else {
unlink($file);
}
}
rmdir($dirPath);
}
【讨论】:
已经有很多解决方案,还有另一种可能,使用 PHP 箭头函数的代码更少:
function rrmdir(string $directory): bool
{
array_map(fn (string $file) => is_dir($file) ? rrmdir($file) : unlink($file), glob($directory . '/' . '*'));
return rmdir($directory);
}
【讨论】:
function delTree($dir) {
$files = array_diff(scandir($dir), array('.','..'));
foreach ($files as $file)
(is_dir("$dir/$file")) ? delTree("$dir/$file") : @unlink("$dir/$file");
return @rmdir($dir);
}
【讨论】: