删除有文件的目录?

我想知道,删除一个包含所有文件的目录最简单的方法是什么?

我使用rmdir(PATH . '/' . $value);来删除一个文件夹,但是,如果其中有文件,我就不能删除它。

434177 次浏览

现在至少有两种选择。

  1. 在删除文件夹之前,删除它所有的文件和文件夹(这意味着递归!)这里有一个例子:

    public static function deleteDir($dirPath) {
    if (! is_dir($dirPath)) {
    throw new InvalidArgumentException("$dirPath must be a directory");
    }
    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
    $dirPath .= '/';
    }
    $files = glob($dirPath . '*', GLOB_MARK);
    foreach ($files as $file) {
    if (is_dir($file)) {
    self::deleteDir($file);
    } else {
    unlink($file);
    }
    }
    rmdir($dirPath);
    }
    
  2. And if you are using 5.2+ you can use a RecursiveIterator to do it without implementing the recursion yourself:

    $dir = 'samples' . DIRECTORY_SEPARATOR . 'sampledirtree';
    $it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
    $files = new RecursiveIteratorIterator($it,
    RecursiveIteratorIterator::CHILD_FIRST);
    foreach($files as $file) {
    if ($file->isDir()){
    rmdir($file->getRealPath());
    } else {
    unlink($file->getRealPath());
    }
    }
    rmdir($dir);
    

删除一个包含所有文件的目录最简单的方法是什么?

system("rm -rf ".escapeshellarg($dir));

完成工作的简短函数:

function deleteDir($path) {
return is_file($path) ?
@unlink($path) :
array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

我在Utils类中使用它,就像这样:

class Utils {
public static function deleteDir($path) {
$class_func = array(__CLASS__, __FUNCTION__);
return is_file($path) ?
@unlink($path) :
array_map($class_func, glob($path.'/*')) == @rmdir($path);
}
}

能力越大,责任越大:当你用空值调用这个函数时,它将删除根目录(/)开始的文件。为了安全起见,你可以检查path是否为空:

function deleteDir($path) {
if (empty($path)) {
return false;
}
return is_file($path) ?
@unlink($path) :
array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}

我更喜欢这个,因为它仍然在成功时返回TRUE,失败时返回FALSE,而且它还防止了一个错误,即一个空路径可能会尝试删除'/*'中的所有内容!!:

function deleteDir($path)
{
return !empty($path) && is_file($path) ?
@unlink($path) :
(array_reduce(glob($path.'/*'), function ($r, $i) { return $r && deleteDir($i); }, TRUE)) && @rmdir($path);
}

这是一个更短的版本,对我来说很好

function deleteDirectory($dirPath) {
if (is_dir($dirPath)) {
$objects = scandir($dirPath);
foreach ($objects as $object) {
if ($object != "." && $object !="..") {
if (filetype($dirPath . DIRECTORY_SEPARATOR . $object) == "dir") {
deleteDirectory($dirPath . DIRECTORY_SEPARATOR . $object);
} else {
unlink($dirPath . DIRECTORY_SEPARATOR . $object);
}
}
}
reset($objects);
rmdir($dirPath);
}
}

这里有一个简单的解决办法

$dirname = $_POST['d'];
$folder_handler = dir($dirname);
while ($file = $folder_handler->read()) {
if ($file == "." || $file == "..")
continue;
unlink($dirname.'/'.$file);


}
$folder_handler->close();
rmdir($dirname);

正如在PHP手册中关于rmdir()(参见http://php.net/manual/es/function.rmdir.php)的大多数投票评论中所看到的,glob()函数不返回隐藏文件。scandir()是作为解决该问题的替代方案提供的。

这里描述的算法(在我的情况下就像一个魅力)是:

<?php
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);
}
?>

像这样的东西?

function delete_folder($folder) {
$glob = glob($folder);
foreach ($glob as $g) {
if (!is_dir($g)) {
unlink($g);
} else {
delete_folder("$g/*");
rmdir($g);
}
}
}

这里你有一个漂亮和简单的递归删除源目录下的所有文件,包括该目录:

function delete_dir($src) {
$dir = opendir($src);
while(false !== ( $file = readdir($dir)) ) {
if (( $file != '.' ) && ( $file != '..' )) {
if ( is_dir($src . '/' . $file) ) {
delete_dir($src . '/' . $file);
}
else {
unlink($src . '/' . $file);
}
}
}
closedir($dir);
rmdir($src);


}

函数是基于复制目录所做的递归。你可以在这里找到这个函数: 使用php将一个目录的全部内容复制到另一个目录 < / p >

<?php
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);
}
}
?>

你试过上述代码从php.net吗

为我工作吧

windows:

system("rmdir ".escapeshellarg($path) . " /s /q");

对alcuadrado的代码稍加修改- glob看不到来自.htaccess这样的点的文件名,所以我使用scandir和脚本删除本身-检查__FILE__

function deleteDir($dirPath) {
if (!is_dir($dirPath)) {
throw new InvalidArgumentException("$dirPath must be a directory");
}
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
$dirPath .= '/';
}
$files = scandir($dirPath);
foreach ($files as $file) {
if ($file === '.' || $file === '..') continue;
if (is_dir($dirPath.$file)) {
deleteDir($dirPath.$file);
} else {
if ($dirPath.$file !== __FILE__) {
unlink($dirPath.$file);
}
}
}
rmdir($dirPath);
}

我通常用它来删除文件夹中的所有文件:

array_map('unlink', glob("$dirname/*.*"));

然后你就可以做了

rmdir($dirname);

类似Playnox的解决方案,但有优雅的内置DirectoryIterator:

function delete_directory($dirPath){
if(is_dir($dirPath)){
$objects=new DirectoryIterator($dirPath);
foreach ($objects as $object){
if(!$object->isDot()){
if($object->isDir()){
delete_directory($object->getPathname());
}else{
unlink($object->getPathname());
}
}
}
rmdir($dirPath);
}else{
throw new Exception(__FUNCTION__.'(dirPath): dirPath is not a directory!');
}
}

对我来说最好的解决方案

my_folder_delete("../path/folder");

代码:

function my_folder_delete($path) {
if(!empty($path) && is_dir($path) ){
$dir  = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS); //upper dirs are not included,otherwise DISASTER HAPPENS :)
$files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($files as $f) {if (is_file($f)) {unlink($f);} else {$empty_dirs[] = $f;} } if (!empty($empty_dirs)) {foreach ($empty_dirs as $eachDir) {rmdir($eachDir);}} rmdir($path);
}
}

注。记住!
不要将空值传递给任何目录删除函数!!(总是备份它们,否则有一天你可能会遇到灾难!!)

你可以使用Symfony的文件系统 (代码):

// composer require symfony/filesystem


use Symfony\Component\Filesystem\Filesystem;


(new Filesystem)->remove($dir);

但是,我不能用这个方法删除一些复杂的目录结构,所以首先您应该尝试一下,以确保它能正常工作。

< p > < br > 我可以使用Windows特定的实现删除上述目录结构:

$dir = strtr($dir, '/', '\\');
// quotes are important, otherwise one could
// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');
< p > < br > 为了完整起见,这里是我的一个旧代码:

function xrmdir($dir) {
$items = scandir($dir);
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
$path = $dir.'/'.$item;
if (is_dir($path)) {
xrmdir($path);
} else {
unlink($path);
}
}
rmdir($dir);
}

删除文件夹
中的所有文件 array_map('unlink', glob("$directory/*.*"));
删除文件夹中所有的。*-文件(不带"."和"..")
. txt array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
现在删除文件夹本身
rmdir($directory) < / p >

我不记得从哪里复制了这个函数,但它看起来没有列出,它是为我工作

function rm_rf($path) {
if (@is_dir($path) && is_writable($path)) {
$dp = opendir($path);
while ($ent = readdir($dp)) {
if ($ent == '.' || $ent == '..') {
continue;
}
$file = $path . DIRECTORY_SEPARATOR . $ent;
if (@is_dir($file)) {
rm_rf($file);
} elseif (is_writable($file)) {
unlink($file);
} else {
echo $file . "is not writable and cannot be removed. Please fix the permission or select a new path.\n";
}
}
closedir($dp);
return rmdir($path);
} else {
return @unlink($path);
}
}

那么这个呢:

function recursiveDelete($dirPath, $deleteParent = true){
foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) {
$path->isFile() ? unlink($path->getPathname()) : rmdir($path->getPathname());
}
if($deleteParent) rmdir($dirPath);
}

平台独立代码。

从PHP.net获取回答

if(PHP_OS === 'Windows')
{
exec("rd /s /q {$path}");
}
else
{
exec("rm -rf {$path}");
}

简单易行…

$dir ='pathtodir';
if (is_dir($dir)) {
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
if ($filename->isDir()) continue;
unlink($filename);
}
rmdir($dir);
}

2美分添加到上面的这个答案中,顺便说一句,这很棒

在glob(或类似)函数扫描/读取目录后,添加一个条件来检查响应是否为空,否则将抛出invalid argument supplied for foreach()警告。所以…

if( ! empty( $files ) )
{
foreach( $files as $file )
{
// do your stuff here...
}
}

我的完整函数(作为对象方法):

    private function recursiveRemoveDirectory( $directory )
{
if( ! is_dir( $directory ) )
{
throw new InvalidArgumentException( "$directory must be a directory" );
}


if( substr( $directory, strlen( $directory ) - 1, 1 ) != '/' )
{
$directory .= '/';
}


$files = glob( $directory . "*" );


if( ! empty( $files ) )
{
foreach( $files as $file )
{
if( is_dir( $file ) )
{
$this->recursiveRemoveDirectory( $file );
}
else
{
unlink( $file );
}
}
}
rmdir( $directory );


} // END recursiveRemoveDirectory()

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);
}
?>

我想通过@Vijit处理符号链接的评论来扩展@alcuadrado的答案。首先,使用getRealPath()。但是,如果你有任何符号链接是文件夹,它会失败,因为它会尝试在链接上调用rmdir -所以你需要额外的检查。

$it = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
foreach($files as $file) {
if ($file->isLink()) {
unlink($file->getPathname());
} else if ($file->isDir()){
rmdir($file->getPathname());
} else {
unlink($file->getPathname());
}
}
rmdir($dir);

例如Linux服务器:exec('rm -f -r ' . $cache_folder . '/*');

这里有一个完美的解决方案:

function unlink_r($from) {
if (!file_exists($from)) {return false;}
$dir = opendir($from);
while (false !== ($file = readdir($dir))) {
if ($file == '.' OR $file == '..') {continue;}


if (is_dir($from . DIRECTORY_SEPARATOR . $file)) {
unlink_r($from . DIRECTORY_SEPARATOR . $file);
}
else {
unlink($from . DIRECTORY_SEPARATOR . $file);
}
}
rmdir($from);
closedir($dir);
return true;
}

这个呢?

function Delete_Directory($Dir)
{
if(is_dir($Dir))
{
$files = glob( $Dir . '*', GLOB_MARK ); //GLOB_MARK adds a slash to directories returned


foreach( $files as $file )
{
Delete_Directory( $file );
}
if(file_exists($Dir))
{
rmdir($Dir);
}
}
elseif(is_file($Dir))
{
unlink( $Dir );
}
}
< p >具有: https://paulund.co.uk/php-delete-directory-and-files-in-directory < / p >

使用DirectoryIterator等价于之前的答案…

function deleteFolder($rootPath)
{
foreach(new DirectoryIterator($rootPath) as $fileToDelete)
{
if($fileToDelete->isDot()) continue;
if ($fileToDelete->isFile())
unlink($fileToDelete->getPathName());
if ($fileToDelete->isDir())
deleteFolder($fileToDelete->getPathName());
}


rmdir($rootPath);
}

这个对我很有用:

function removeDirectory($path) {
$files = glob($path . '/*');
foreach ($files as $file) {
is_dir($file) ? removeDirectory($file) : unlink($file);
}
rmdir($path);
return;
}

如果你不确定,给定的路径是目录或文件,那么你可以使用这个函数删除路径

function deletePath($path) {
if(is_file($path)){
unlink($path);
} elseif(is_dir($path)){
$path = (substr($path, -1) !== DIRECTORY_SEPARATOR) ? $path . DIRECTORY_SEPARATOR : $path;
$files = glob($path . '*');
foreach ($files as $file) {
deleteDirPath($file);
}
rmdir($path);
} else {
return false;
}
}

您可以尝试如下:

/*
* Remove the directory and its content (all files and subdirectories).
* @param string $dir the directory name
*/
function rmrf($dir) {
foreach (glob($dir) as $file) {
if (is_dir($file)) {
rmrf("$file/*");
rmdir($file);
} else {
unlink($file);
}
}
}

你可以尝试这个简单的12行代码删除文件夹或文件夹文件… 快乐的编码…;):) < / p >

function deleteAll($str) {
if (is_file($str)) {
return unlink($str);
}
elseif (is_dir($str)) {
$scan = glob(rtrim($str,'/').'/*');
foreach($scan as $index=>$path) {
$this->deleteAll($path);
}
return @rmdir($str);
}
}

您可以复制YII帮助程序

$directory (string) -递归删除。

$options (array) -用于删除目录。 有效的选项是: traverseSymlinks:布尔值,是否也应该遍历指向目录的符号链接。默认值为false,这意味着符号链接目录的内容不会被删除。在默认情况下,只有符号链接将被删除

public static function removeDirectory($directory,$options=array())
{
if(!isset($options['traverseSymlinks']))
$options['traverseSymlinks']=false;
$items=glob($directory.DIRECTORY_SEPARATOR.'{,.}*',GLOB_MARK | GLOB_BRACE);
foreach($items as $item)
{
if(basename($item)=='.' || basename($item)=='..')
continue;
if(substr($item,-1)==DIRECTORY_SEPARATOR)
{
if(!$options['traverseSymlinks'] && is_link(rtrim($item,DIRECTORY_SEPARATOR)))
unlink(rtrim($item,DIRECTORY_SEPARATOR));
else
self::removeDirectory($item,$options);
}
else
unlink($item);
}
if(is_dir($directory=rtrim($directory,'\\/')))
{
if(is_link($directory))
unlink($directory);
else
rmdir($directory);
}
}

我不敢相信有30多个答案。在PHP中递归删除一个文件夹可能需要几分钟,这取决于目录的深度和其中的文件数量!你可以用一行代码做到这一点…

shell_exec("rm -rf " . $dir);

如果你关心删除整个文件系统,首先要确保你的$dir路径是你想要的。永远不要允许用户输入一些可以直接删除文件的东西,而不首先严格验证输入。这是基本的编码实践。