我想知道,删除其中包含所有文件的目录的最简单方法是什么?
我正在rmdir(PATH . '/' . $value);
删除一个文件夹,但是,如果其中有文件,我将无法删除。
fclose($create_file);
,删除文件时得到Warning: unlink(created_file.xml): Permission denied in...
。因此,为避免此类错误,必须关闭创建的文件。
我想知道,删除其中包含所有文件的目录的最简单方法是什么?
我正在rmdir(PATH . '/' . $value);
删除一个文件夹,但是,如果其中有文件,我将无法删除。
fclose($create_file);
,删除文件时得到Warning: unlink(created_file.xml): Permission denied in...
。因此,为避免此类错误,必须关闭创建的文件。
Answers:
如今至少有两种选择。
删除文件夹之前,请删除其所有文件和文件夹(这意味着递归!)。这是一个例子:
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);
}
如果您使用的是5.2+,则可以使用RecursiveIterator来实现,而无需自己实现递归:
$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);
.
和..
),并且删除解析的路径,而不是实际的路径。
scandir
函数来获取文件夹列表。只要确保您过滤了“。” 和结果列表中的“ ..”文件。
explode()
获取路径。alanhogan.com/tips/php/directory-separator-not-necessary
我通常使用它来删除文件夹中的所有文件:
array_map('unlink', glob("$dirname/*.*"));
然后你可以做
rmdir($dirname);
array_map('unlink', glob("$dirname/*"));
这仍然不允许您删除嵌套在文件夹中的目录。
删除其中包含所有文件的目录的最简单方法是什么?
system("rm -rf ".escapeshellarg($dir));
$dir
生成/提供的方式,您可能需要进行一些其他预处理,以确保安全并避免错误。例如,如果其中$dir
可能有未转义的空间或分号,则可能会有不良的副作用。使用诸如此类之类的答案的情况并非如此,rmdir()
因为它将为您处理特殊字符。
system('rmdir '.escapeshellarg($path).' /s /q');
做这项工作的简短功能:
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);
}
}
功能强大,责任重大:当您使用空值调用此函数时,它将删除以root(/
)开头的文件。作为保障,您可以检查路径是否为空:
function deleteDir($path) {
if (empty($path)) {
return false;
}
return is_file($path) ?
@unlink($path) :
array_map(__FUNCTION__, glob($path.'/*')) == @rmdir($path);
}
$this_func = array(__CLASS__, __FUNCTION__);
array_map($class_func, glob($path.'/*')) == @rmdir($path)
吗?我猜他正在遍历子文件夹,但是== @rmdir部分有什么作用?<布尔数组> == <布尔>如何返回答案?它是否检查递归的每个返回值是否与右边的布尔值相同?
array_map(...)
删除目录中的所有文件,@rmdir(...)
删除目录本身。
/
,所以我在自己的帖子中添加了受保护的版本。
正如有关PHP手册页rmdir()
(请参阅http://php.net/manual/es/function.rmdir.php)上大多数投票表决的评论所示,glob()
function不返回隐藏文件。 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);
}
?>
$file
)中找到的条目是目录还是文件。 "$dir/$file"
与相同$dir . "/" . $file
。
这是一个较短的版本,对我来说很棒
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);
}
}
// composer require symfony/filesystem
use Symfony\Component\Filesystem\Filesystem;
(new Filesystem)->remove($dir);
但是,我无法使用此方法删除一些复杂的目录结构,因此首先应尝试使用它以确保其正常工作。
我可以使用Windows特定的实现删除上述目录结构:
$dir = strtr($dir, '/', '\\');
// quotes are important, otherwise one could
// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');
为了完整起见,这是我的旧代码:
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);
}
在这里,您可以通过一种不错而又简单的递归删除源目录中的所有文件,包括该目录:
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将目录的整个内容复制到另一个目录
最适合我的解决方案
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);
}
}
ps记住!
不要将空值传递给任何目录删除功能!!!(始终备份它们,否则有一天您可能会遭受灾难!)
那这个呢:
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);
}
您可以尝试如下操作:
/*
* 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);
}
}
}
我想用@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);
使用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);
}
略微修改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);
}
Linux服务器示例: exec('rm -f -r ' . $cache_folder . '/*');
2美分加到这个答案上述,这是很好的BTW
在您的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()
这是完美的解决方案:
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;
}
您可以复制YII助手
$ directory(字符串)-递归删除。
$ options(数组)-用于目录删除。有效选项包括: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);
}
}
<?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的Obove代码
为我工作好
类似于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!');
}
}
我不记得我从哪里复制了此函数,但它似乎没有列出,并且对我有用
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 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 );
}
}
参考:https : //paulund.co.uk/php-delete-directory-and-files-in-directory
如果不确定,给定路径是目录还是文件,则可以使用此功能删除路径
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;
}
}