Просто хочу отметить. Я создал несколько файлов, и если во время процесса выдается какая-то ошибка, то нужно удалить ранее созданные файлы. Когда создали файлы, забыли использовать, fclose($create_file);а когда удалили, достали Warning: unlink(created_file.xml): Permission denied in.... Поэтому, чтобы избежать таких ошибок, необходимо закрыть созданные файлы.
В настоящее время доступно как минимум два варианта.
Перед удалением папки удалите все ее файлы и папки (а это означает рекурсию!). Вот пример:
publicstaticfunction deleteDir($dirPath){if(! is_dir($dirPath)){thrownewInvalidArgumentException("$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, чтобы сделать это без самостоятельной реализации рекурсии:
Ваша вторая реализация несколько опасна: она не проверяет точки ( .и ..) и удаляет разрешенный путь, а не фактический.
Аликс Аксель
9
небольшое дополнение :-) glob () не поддерживает такие файлы, как .htaccess. Я использовал функцию для очистки каталогов, созданных KCFinder (плагин CKEditor), который генерирует как .htaccess, так и .thumbs (файл + папка). Вместо этого я использовал scandirфункцию, чтобы получить список папок. Просто убедитесь, что вы фильтруете '.' и '..' файлы из списка результатов.
Джошуа - Пендо
25
DIRECTORY_SEPARATOR не является необходимым , когда вы строите пути , чтобы отправить к зева. Windows также будет принимать косые черты. Это в основном полезно для explode()поиска пути, взятого из ОС. alanhogan.com/tips/php/directory-separator-not-needed
ReactiveRaven
5
В дополнение к использованию @Alix Axel здесь [SplFileInfo :: getRealPath ()] ( php.net/manual/en/splfileinfo.getrealpath.php ) не очень хорошая идея. Этот метод расширяет все символические ссылки, то есть будет удален реальный файл откуда-то вместо символической ссылки из целевого каталога. Вместо этого вы должны использовать SplFileInfo :: getPathname ().
Виджит
2
Я согласен с @Vijit, используйте getPathname () вместо getRealPath (). Он делает то же самое, не удаляя больше, чем вы ожидаете, если найдены символические ссылки.
JoeMoe1984,
196
Я обычно использую это, чтобы удалить все файлы в папке:
Это не удаляет папки рекурсивно; это работает, только если в папке есть только обычные файлы, все из которых имеют расширения.
Mgnb
5
Если рекурсия не нужна, то это лучший и самый простой ответ. Спасибо!
Eisbehr
2
Чтобы удалить все файлы из папки, а не только файлы с расширениями, используйте glob следующим образом: array_map('unlink', glob("$dirname/*"));Это по-прежнему не позволяет удалять каталоги, вложенные в папку.
Кремува,
Обратите внимание, что это также удалит точечные (скрытые) файлы.
BadHorsie
84
Какой самый простой способ удалить каталог со всеми его файлами в нем?
Я надеюсь, что вы не серьезно. Что произойдет , если $ НАПРАВЛ /
пиксельной Разработчик
108
@ Точно так же, как с любым из приведенных выше кодов. Не так ли?
Твой здравый смысл
7
Обратите внимание, что в зависимости от того, как $dirгенерируется / предоставляется, вам может потребоваться выполнить некоторую дополнительную предварительную обработку, чтобы быть в безопасности и избежать ошибок. Например, если в нем $dirможет быть свободное пространство или точка с запятой, могут возникнуть нежелательные побочные эффекты. Это не относится к ответам, которые используют такие вещи, как, rmdir()потому что он будет обрабатывать специальные символы для вас.
Тротт
5
Версия для Windows:system('rmdir '.escapeshellarg($path).' /s /q');
Cypher
2
@ThePixelDeveloper, вы не должны беспокоиться об удалении /, это будет работать, только если вы запустите скрипт в командной строке как root, потому что в сети все происходит как пользователь apache
Бен
49
Короткая функция, которая делает работу:
function deleteDir($path){return is_file($path)?@unlink($path):
array_map(__FUNCTION__, glob($path.'/*'))==@rmdir($path);}
С большой силой приходит большая ответственность : когда вы вызываете эту функцию с пустым значением, она удаляет файлы, начинающиеся с root ( /). В качестве гарантии вы можете проверить, если путь пуст:
function deleteDir($path){if(empty($path)){returnfalse;}return is_file($path)?@unlink($path):
array_map(__FUNCTION__, glob($path.'/*'))==@rmdir($path);}
Статическая не работает, потому что $ this === NULL, когда вы вызываете статическую функцию в классе. Это будет работать, если$this_func = array(__CLASS__, __FUNCTION__);
Мэтт Коннолли
2
Может кто-нибудь объяснить линию array_map($class_func, glob($path.'/*')) == @rmdir($path)? Я думаю, он просматривает подпапки, но что делает часть == @rmdir? Как <массив логических значений> == <логическое> возвращает ответ? Проверяет, совпадает ли каждое возвращаемое значение рекурсии с логическим значением справа?
arviman
2
Это трюк, чтобы объединить два утверждения в одно утверждение. Это связано с тем, что троичные операторы допускают только один оператор на аргумент. array_map(...)удаляет все файлы в каталоге, @rmdir(...)удаляет сам каталог.
Блейз
3
Быть осторожен! Эта функция не проверяет, существует ли путь на самом деле. Если вы передадите пустой аргумент, функция начнет удалять файлы, начиная с корня! Добавьте проверку работоспособности на ваш путь перед запуском этой функции.
Тату Ульманен,
3
Некоторые люди не увидели комментарий Тату и рекурсивно удалили /, поэтому я добавил защищенную версию к своему сообщению.
Блейз
22
Как видно из наиболее популярных комментариев на странице справки по 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);}?>
Можете ли вы объяснить, is_dir ("$ dir / $ file") - не встречал с параметром "$ dir / $ file"
Игорь Л.
Что вы имеете в виду? Он проверяет, является ли запись, найденная в каталоге ( $file), каталогом или файлом. "$dir/$file"так же, как $dir . "/" . $file.
Немецкий Latorre
Я, честно говоря, не знал, что вы можете объединить переменные, как это :) THX
Игорь Л.
18
Это более короткая версия отлично работает для меня
Однако я не мог удалить некоторые сложные структуры каталогов с помощью этого метода, поэтому сначала вы должны попробовать его, чтобы убедиться, что он работает правильно.
Я мог бы удалить указанную структуру каталогов, используя конкретную реализацию 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 my_folder_delete($path){if(!empty($path)&& is_dir($path)){
$dir =newRecursiveDirectoryIterator($path,RecursiveDirectoryIterator::SKIP_DOTS);//upper dirs are not included,otherwise DISASTER HAPPENS :)
$files =newRecursiveIteratorIterator($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);}}
ПОМНИТЕ! НЕ передавайте ПУСТЫЕ ЗНАЧЕНИЯ никаким функциям удаления Каталога !!! (резервируйте их всегда, иначе однажды вы можете получить БЕДСТВО !!)
/*
* 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);}}}
Я предпочитаю это, потому что он по-прежнему возвращает 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);}
Я хочу расширить ответ @alcuadrado комментарием @Vijit для обработки символических ссылок. Во-первых, используйте getRealPath (). Но затем, если у вас есть какие-либо символические ссылки, которые являются папками, он потерпит неудачу, так как попытается вызвать rmdir для ссылки - так что вам нужна дополнительная проверка.
$it =newRecursiveDirectoryIterator($dir,RecursiveDirectoryIterator::SKIP_DOTS);
$files =newRecursiveIteratorIterator($it,RecursiveIteratorIterator::CHILD_FIRST);foreach($files as $file){if($file->isLink()){
unlink($file->getPathname());}elseif($file->isDir()){
rmdir($file->getPathname());}else{
unlink($file->getPathname());}}
rmdir($dir);
Немного изменил код alcuadrado - globне вижу файлов с именами из таких точек, как, .htaccessпоэтому я использую scandir и скрипт удаляет сам себя - проверьте __FILE__.
function deleteDir($dirPath){if(!is_dir($dirPath)){thrownewInvalidArgumentException("$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);}
2 цента, чтобы добавить к этому ответу выше, что здорово, кстати
После того, как ваша функция glob (или аналогичная) отсканирует / прочитает каталог, добавьте условие, чтобы убедиться, что ответ не пустой, или invalid argument supplied for foreach()будет выдано предупреждение. Так...
if(! empty( $files )){foreach( $files as $file ){// do your stuff here...}}
Моя полная функция (как метод объекта):
privatefunction recursiveRemoveDirectory( $directory ){if(! is_dir( $directory )){thrownewInvalidArgumentException("$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()
$ options (array) - для удаления каталога. Допустимые параметры: traverseSymlinks: boolean, следует ли проходить символические ссылки на каталоги. По умолчанию это falseозначает, что содержимое каталога с символическими ссылками не будет удалено. В этом случае по умолчанию будет удалена только символическая ссылка.
Как и решение Playnox, но с элегантным встроенным DirectoryIterator:
function delete_directory($dirPath){if(is_dir($dirPath)){
$objects=newDirectoryIterator($dirPath);foreach($objects as $object){if(!$object->isDot()){if($object->isDir()){
delete_directory($object->getPathname());}else{
unlink($object->getPathname());}}}
rmdir($dirPath);}else{thrownewException(__FUNCTION__.'(dirPath): dirPath is not a directory!');}}
fclose($create_file);
а когда удалили, досталиWarning: unlink(created_file.xml): Permission denied in...
. Поэтому, чтобы избежать таких ошибок, необходимо закрыть созданные файлы.Ответы:
В настоящее время доступно как минимум два варианта.
Перед удалением папки удалите все ее файлы и папки (а это означает рекурсию!). Вот пример:
И если вы используете 5.2+, вы можете использовать RecursiveIterator, чтобы сделать это без самостоятельной реализации рекурсии:
источник
.
и..
) и удаляет разрешенный путь, а не фактический.scandir
функцию, чтобы получить список папок. Просто убедитесь, что вы фильтруете '.' и '..' файлы из списка результатов.explode()
поиска пути, взятого из ОС. alanhogan.com/tips/php/directory-separator-not-neededЯ обычно использую это, чтобы удалить все файлы в папке:
И тогда вы можете сделать
источник
array_map('unlink', glob("$dirname/*"));
Это по-прежнему не позволяет удалять каталоги, вложенные в папку.источник
$dir
генерируется / предоставляется, вам может потребоваться выполнить некоторую дополнительную предварительную обработку, чтобы быть в безопасности и избежать ошибок. Например, если в нем$dir
может быть свободное пространство или точка с запятой, могут возникнуть нежелательные побочные эффекты. Это не относится к ответам, которые используют такие вещи, как,rmdir()
потому что он будет обрабатывать специальные символы для вас.system('rmdir '.escapeshellarg($path).' /s /q');
Короткая функция, которая делает работу:
Я использую его в классе Utils следующим образом:
С большой силой приходит большая ответственность : когда вы вызываете эту функцию с пустым значением, она удаляет файлы, начинающиеся с root (
/
). В качестве гарантии вы можете проверить, если путь пуст:источник
$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()
функция не возвращает скрытые файлы.scandir()
предоставляется в качестве альтернативы, которая решает эту проблему.Алгоритм, описанный там (который работал как шарм в моем случае):
источник
$file
), каталогом или файлом."$dir/$file"
так же, как$dir . "/" . $file
.Это более короткая версия отлично работает для меня
источник
Вы можете использовать файловую систему Symfony ( код ):
Однако я не мог удалить некоторые сложные структуры каталогов с помощью этого метода, поэтому сначала вы должны попробовать его, чтобы убедиться, что он работает правильно.
Я мог бы удалить указанную структуру каталогов, используя конкретную реализацию Windows:
И просто для полноты, вот мой старый код:
источник
Здесь у вас есть одна хорошая и простая рекурсия для удаления всех файлов в исходном каталоге, включая этот каталог:
Функция основана на рекурсии, выполненной для копирования каталога. Вы можете найти эту функцию здесь: Скопируйте все содержимое одного каталога в другой, используя php.
источник
Лучшее решение для меня
код:
ПОМНИТЕ!
НЕ передавайте ПУСТЫЕ ЗНАЧЕНИЯ никаким функциям удаления Каталога !!! (резервируйте их всегда, иначе однажды вы можете получить БЕДСТВО !!)
источник
Как насчет этого:
источник
Функция glob не возвращает скрытые файлы, поэтому scandir может быть более полезен при рекурсивном удалении дерева.
источник
Вы можете попробовать следующим образом:
источник
Я предпочитаю это, потому что он по-прежнему возвращает TRUE, если он успешен, и FALSE, если он терпит неудачу, и это также предотвращает ошибку, при которой пустой путь может попытаться удалить все из '/ *' !!:
источник
Я хочу расширить ответ @alcuadrado комментарием @Vijit для обработки символических ссылок. Во-первых, используйте getRealPath (). Но затем, если у вас есть какие-либо символические ссылки, которые являются папками, он потерпит неудачу, так как попытается вызвать rmdir для ссылки - так что вам нужна дополнительная проверка.
источник
Использование DirectoryIterator эквивалент предыдущего ответа ...
источник
Этот работает для меня:
источник
Что-то вроде этого?
источник
Немного изменил код alcuadrado -
glob
не вижу файлов с именами из таких точек, как,.htaccess
поэтому я использую scandir и скрипт удаляет сам себя - проверьте__FILE__
.источник
Пример для сервера Linux:
exec('rm -f -r ' . $cache_folder . '/*');
источник
Удалить все файлы в папке
array_map('unlink', glob("$directory/*.*"));
Удалить все. * - Файлы в папке (без:. "И" .. ")
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
Теперь удалите саму папку
rmdir($directory)
источник
2 цента, чтобы добавить к этому ответу выше, что здорово, кстати
После того, как ваша функция glob (или аналогичная) отсканирует / прочитает каталог, добавьте условие, чтобы убедиться, что ответ не пустой, или
invalid argument supplied for foreach()
будет выдано предупреждение. Так...Моя полная функция (как метод объекта):
источник
Вот решение, которое работает идеально:
источник
Вы можете скопировать помощников YII
$ directory (string) - рекурсивно удаляется.
$ options (array) - для удаления каталога. Допустимые параметры: traverseSymlinks: boolean, следует ли проходить символические ссылки на каталоги. По умолчанию это
false
означает, что содержимое каталога с символическими ссылками не будет удалено. В этом случае по умолчанию будет удалена только символическая ссылка.источник
Испытали свой код выше с php.net
Работа у меня нормально
источник
Для окон:
источник
Как и решение Playnox, но с элегантным встроенным DirectoryIterator:
источник
Я не помню, откуда я скопировал эту функцию, но похоже, что ее нет в списке, и она работает для меня
источник
Просто и легко ...
источник
Как насчет этого?
Ссылка: https://paulund.co.uk/php-delete-directory-and-files-in-directory
источник
Если вы не уверены, что заданный путь является каталогом или файлом, вы можете использовать эту функцию для удаления пути
источник