Solo quiero tener en cuenta. Creé varios archivos y si durante el proceso recibo algún error, entonces necesito eliminar los archivos creados previamente. Cuando se crearon los archivos, se olvidó de usarlos fclose($create_file);y cuando se eliminaron, obtuve Warning: unlink(created_file.xml): Permission denied in.... Entonces, para evitar tales errores, debe cerrar los archivos creados.
Hay al menos dos opciones disponibles en la actualidad.
Antes de eliminar la carpeta, elimine todos sus archivos y carpetas (¡y esto significa recurrencia!). Aquí hay un ejemplo:
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);}
Y si está utilizando 5.2+, puede usar un RecursiveIterator para hacerlo sin implementar la recursividad usted mismo:
Su segunda implementación es algo peligrosa: no comprueba los puntos ( .y ..) y elimina la ruta resuelta, no la real.
Alix Axel
99
pequeño complemento :-) glob () no es compatible con archivos como .htaccess. Utilicé la función para borrar directorios creados por KCFinder (complemento CKEditor) que genera tanto .htaccess como .thumbs (archivo + carpeta). En su lugar, utilicé la scandirfunción para obtener la lista de carpetas. Solo asegúrese de filtrar el '.' y '...' archivos de la lista de resultados.
Joshua - Pendo
25
DIRECTORY_SEPARATOR no es necesario cuando está creando rutas para enviar al sistema operativo. Windows también aceptará barras diagonales. Es principalmente útil para explode()trazar una ruta tomada del sistema operativo. alanhogan.com/tips/php/directory-separator-not-necessary
ReactiveRaven
55
Además de @Alix Axel, usar aquí [SplFileInfo :: getRealPath ()] ( php.net/manual/en/splfileinfo.getrealpath.php ) no es una buena idea. Este método expande todos los enlaces simbólicos, es decir, se eliminará un archivo real de algún lugar en lugar de un enlace simbólico del directorio de destino. Debería usar SplFileInfo :: getPathname () en su lugar.
Vijit
2
Estoy de acuerdo con @Vijit, use getPathname () en lugar de getRealPath (). Hace lo mismo sin eliminar más de lo que espera si se encuentran enlaces simbólicos.
JoeMoe1984
196
Generalmente uso esto para eliminar todos los archivos en una carpeta:
Esto no elimina carpetas de forma recursiva; solo funciona si la carpeta solo contiene archivos regulares, todos los cuales tienen extensiones de archivo.
mgnb
55
Si no se necesita recurrencia, esta es la mejor y más simple respuesta hasta ahora. ¡Gracias!
eisbehr
2
Para eliminar todos los archivos de una carpeta, no solo los que tienen extensiones, use glob de la siguiente manera: array_map('unlink', glob("$dirname/*"));Esto aún no le permite eliminar directorios anidados en la carpeta.
kremuwa
Tenga en cuenta que esto también eliminará los archivos de puntos (ocultos).
BadHorsie
85
¿Cuál es la forma más fácil de eliminar un directorio con todos sus archivos?
Espero que no hables en serio. ¿Qué sucede si $ dir es /
The Pixel Developer
108
@ Lo mismo que con cualquiera de los códigos anteriores. ¿No es así?
Su sentido común
77
Tenga en cuenta que, dependiendo de cómo $dirse genere / proporcione, es posible que deba realizar un preprocesamiento adicional para estar seguro y evitar errores. Por ejemplo, si $dirpudiera tener un espacio sin escape o punto y coma en él, entonces podría haber efectos secundarios indeseables. Este no es el caso con las respuestas que usan cosas como rmdir()porque manejará los caracteres especiales para usted.
Trott
55
Versión de Windows:system('rmdir '.escapeshellarg($path).' /s /q');
Cypher
2
@ThePixelDeveloper no debería preocuparse por eliminar /, esto solo funcionaría si lanzara el script en la línea de comando como root, porque en la web todo sucede como usuario apache
Ben
49
Función corta que hace el trabajo:
function deleteDir($path){return is_file($path)?@unlink($path):
array_map(__FUNCTION__, glob($path.'/*'))==@rmdir($path);}
Con un gran poder viene una gran responsabilidad : cuando llama a esta función con un valor vacío, eliminará los archivos que comienzan en root ( /). Como medida de seguridad, puede verificar si la ruta está vacía:
function deleteDir($path){if(empty($path)){returnfalse;}return is_file($path)?@unlink($path):
array_map(__FUNCTION__, glob($path.'/*'))==@rmdir($path);}
El estático no funciona porque $ this === NULL cuando llama a una función estática en una clase. Funcionaría si$this_func = array(__CLASS__, __FUNCTION__);
Matt Connolly
2
¿Alguien puede explicar la línea array_map($class_func, glob($path.'/*')) == @rmdir($path)? Supongo que está recurriendo a través de las subcarpetas, pero ¿qué hace la parte == @rmdir? ¿Cómo la <matriz de booleanos> == <booleano> devuelve la respuesta? ¿Comprueba si cada valor de retorno de la recursividad es el mismo que el booleano de la derecha?
arviman
2
Es un truco combinar dos declaraciones en una sola declaración. Esto se debe a que los operadores ternarios solo permiten una declaración por argumento. array_map(...)elimina todos los archivos dentro del directorio, @rmdir(...)elimina el directorio en sí.
Blaise
3
¡Ten cuidado! Esta función no comprueba si la ruta realmente existe. Si pasa un argumento vacío, la función comenzará a eliminar archivos a partir de la raíz. Agregue una comprobación de cordura a su ruta antes de ejecutar esta función.
Tatu Ulmanen
3
Algunas personas no vieron el comentario de Tatu y lo borraron recursivamente /, así que agregué una versión protegida a mi publicación.
Blaise
22
Como se ve en el comentario más votado en la página del manual de PHP sobre rmdir()(ver http://php.net/manual/es/function.rmdir.php ), la glob()función no devuelve archivos ocultos. scandir()se proporciona como una alternativa que resuelve ese problema.
El algoritmo descrito allí (que funcionó como un encanto en mi caso) es:
<?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);}?>
¿puede explicar is_dir ("$ dir / $ file")? no se reunió con el parámetro "$ dir / $ file"
Igor L.
¿Qué quieres decir? Comprueba si la entrada encontrada en un directorio ( $file) es un directorio o un archivo. "$dir/$file"es el mismo que $dir . "/" . $file.
Alemán Latorre
Sinceramente, no sabía que puede concatenar variables como esta :) thx
Igor L.
18
Esta es una versión más corta que me funciona muy bien
Sin embargo, no pude eliminar algunas estructuras de directorio complejas con este método, así que primero debes probarlo para asegurarte de que funcione correctamente.
Podría eliminar dicha estructura de directorio utilizando una implementación específica de Windows:
$dir = strtr($dir,'/','\\');// quotes are important, otherwise one could// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');
Y solo por completar, aquí hay un viejo código mío:
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);}}
ps RECUERDA! ¡no pase VALORES VACÍOS a ninguna función de eliminación de Directorio! (¡Respaldarlos siempre, de lo contrario, algún día podrías DESASTRAR!)
/*
* 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);}}}
¡Prefiero esto porque todavía devuelve VERDADERO cuando tiene éxito y FALSO cuando falla, y también evita un error en el que una ruta vacía puede intentar eliminar todo de '/ *'!
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);}
Quiero ampliar la respuesta de @alcuadrado con el comentario de @Vijit para manejar enlaces simbólicos. En primer lugar, use getRealPath (). Pero luego, si tiene enlaces simbólicos que son carpetas, fallará, ya que intentará llamar a rmdir en un enlace, por lo que necesita una comprobación adicional.
$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);
Pequeña modificación del código de alcuadrado: globno veo archivos con nombre de puntos como, .htaccessasí que uso scandir y el script se elimina solo, verifique __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);}
Por lo general, me gusta agregar una comprobación de cordura en $ cache_folder antes de ejecutar rm -rf para evitar errores costosos
glifo
1
Eliminar todos los archivos en la carpeta array_map('unlink', glob("$directory/*.*"));
Eliminar todo. * - Archivos en la carpeta (sin: "." Y "..") array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
Ahora elimine la carpeta en sí rmdir($directory)
2 centavos para agregar a ESTA respuesta anterior, lo cual es genial, por cierto
Después de que su función global (o similar) haya escaneado / leído el directorio, agregue un condicional para verificar que la respuesta no esté vacía, o se invalid argument supplied for foreach()lanzará una advertencia. Entonces...
if(! empty( $files )){foreach( $files as $file ){// do your stuff here...}}
Mi función completa (como método de objeto):
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()
$ directorio (cadena): se eliminará de forma recursiva.
$ opciones (matriz): para eliminar el directorio. Las opciones válidas son: traverseSymlinks: boolean, si los enlaces simbólicos a los directorios también deben atravesarse. El valor predeterminado es false, lo que significa que no se eliminará el contenido del directorio enlazado. Solo el enlace simbólico se eliminaría en ese caso predeterminado.
Como la solución de Playnox, pero con el elegante DirectoryIterator incorporado:
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);
y cuando se eliminaron, obtuveWarning: unlink(created_file.xml): Permission denied in...
. Entonces, para evitar tales errores, debe cerrar los archivos creados.Respuestas:
Hay al menos dos opciones disponibles en la actualidad.
Antes de eliminar la carpeta, elimine todos sus archivos y carpetas (¡y esto significa recurrencia!). Aquí hay un ejemplo:
Y si está utilizando 5.2+, puede usar un RecursiveIterator para hacerlo sin implementar la recursividad usted mismo:
fuente
.
y..
) y elimina la ruta resuelta, no la real.scandir
función para obtener la lista de carpetas. Solo asegúrese de filtrar el '.' y '...' archivos de la lista de resultados.explode()
trazar una ruta tomada del sistema operativo. alanhogan.com/tips/php/directory-separator-not-necessaryGeneralmente uso esto para eliminar todos los archivos en una carpeta:
Y luego puedes hacer
fuente
array_map('unlink', glob("$dirname/*"));
Esto aún no le permite eliminar directorios anidados en la carpeta.fuente
$dir
se genere / proporcione, es posible que deba realizar un preprocesamiento adicional para estar seguro y evitar errores. Por ejemplo, si$dir
pudiera tener un espacio sin escape o punto y coma en él, entonces podría haber efectos secundarios indeseables. Este no es el caso con las respuestas que usan cosas comormdir()
porque manejará los caracteres especiales para usted.system('rmdir '.escapeshellarg($path).' /s /q');
Función corta que hace el trabajo:
Lo uso en una clase de Utils como esta:
Con un gran poder viene una gran responsabilidad : cuando llama a esta función con un valor vacío, eliminará los archivos que comienzan en root (
/
). Como medida de seguridad, puede verificar si la ruta está vacía:fuente
$this_func = array(__CLASS__, __FUNCTION__);
array_map($class_func, glob($path.'/*')) == @rmdir($path)
? Supongo que está recurriendo a través de las subcarpetas, pero ¿qué hace la parte == @rmdir? ¿Cómo la <matriz de booleanos> == <booleano> devuelve la respuesta? ¿Comprueba si cada valor de retorno de la recursividad es el mismo que el booleano de la derecha?array_map(...)
elimina todos los archivos dentro del directorio,@rmdir(...)
elimina el directorio en sí./
, así que agregué una versión protegida a mi publicación.Como se ve en el comentario más votado en la página del manual de PHP sobre
rmdir()
(ver http://php.net/manual/es/function.rmdir.php ), laglob()
función no devuelve archivos ocultos.scandir()
se proporciona como una alternativa que resuelve ese problema.El algoritmo descrito allí (que funcionó como un encanto en mi caso) es:
fuente
$file
) es un directorio o un archivo."$dir/$file"
es el mismo que$dir . "/" . $file
.Esta es una versión más corta que me funciona muy bien
fuente
Puede usar el sistema de archivos de Symfony ( código ):
Sin embargo, no pude eliminar algunas estructuras de directorio complejas con este método, así que primero debes probarlo para asegurarte de que funcione correctamente.
Podría eliminar dicha estructura de directorio utilizando una implementación específica de Windows:
Y solo por completar, aquí hay un viejo código mío:
fuente
Aquí tiene una recursión agradable y simple para eliminar todos los archivos en el directorio de origen, incluido ese directorio:
La función se basa en la recursividad realizada para copiar el directorio. Puede encontrar esa función aquí: Copie todo el contenido de un directorio a otro usando php
fuente
La mejor solución para mi
código:
ps RECUERDA!
¡no pase VALORES VACÍOS a ninguna función de eliminación de Directorio! (¡Respaldarlos siempre, de lo contrario, algún día podrías DESASTRAR!)
fuente
¿Qué hay de esto?
fuente
La función Glob no devuelve los archivos ocultos, por lo tanto, scandir puede ser más útil cuando se trata de eliminar un árbol de forma recursiva.
fuente
Puedes probar lo siguiente:
fuente
¡Prefiero esto porque todavía devuelve VERDADERO cuando tiene éxito y FALSO cuando falla, y también evita un error en el que una ruta vacía puede intentar eliminar todo de '/ *'!
fuente
Quiero ampliar la respuesta de @alcuadrado con el comentario de @Vijit para manejar enlaces simbólicos. En primer lugar, use getRealPath (). Pero luego, si tiene enlaces simbólicos que son carpetas, fallará, ya que intentará llamar a rmdir en un enlace, por lo que necesita una comprobación adicional.
fuente
Usando DirectoryIterator un equivalente de una respuesta anterior ...
fuente
Esta funciona para mí:
fuente
¿Algo como esto?
fuente
Pequeña modificación del código de alcuadrado:
glob
no veo archivos con nombre de puntos como,.htaccess
así que uso scandir y el script se elimina solo, verifique__FILE__
.fuente
Ejemplo para el servidor Linux:
exec('rm -f -r ' . $cache_folder . '/*');
fuente
Eliminar todos los archivos en la carpeta
array_map('unlink', glob("$directory/*.*"));
Eliminar todo. * - Archivos en la carpeta (sin: "." Y "..")
array_map('unlink', array_diff(glob("$directory/.*),array("$directory/.","$directory/..")))
Ahora elimine la carpeta en sí
rmdir($directory)
fuente
2 centavos para agregar a ESTA respuesta anterior, lo cual es genial, por cierto
Después de que su función global (o similar) haya escaneado / leído el directorio, agregue un condicional para verificar que la respuesta no esté vacía, o se
invalid argument supplied for foreach()
lanzará una advertencia. Entonces...Mi función completa (como método de objeto):
fuente
Aquí está la solución que funciona perfectamente:
fuente
Podrías copiar los ayudantes de YII
$ directorio (cadena): se eliminará de forma recursiva.
$ opciones (matriz): para eliminar el directorio. Las opciones válidas son: traverseSymlinks: boolean, si los enlaces simbólicos a los directorios también deben atravesarse. El valor predeterminado es
false
, lo que significa que no se eliminará el contenido del directorio enlazado. Solo el enlace simbólico se eliminaría en ese caso predeterminado.fuente
Haz probado el código obove de php.net
Trabaja para mi bien
fuente
Para ventanas:
fuente
Como la solución de Playnox, pero con el elegante DirectoryIterator incorporado:
fuente
No recuerdo de dónde copié esta función, pero parece que no está en la lista y está funcionando para mí.
fuente
Simple y fácil...
fuente
¿Qué hay de esto?
Referencia: https://paulund.co.uk/php-delete-directory-and-files-in-directory
fuente
Si no está seguro, la ruta dada es un directorio o archivo, entonces puede usar esta función para eliminar la ruta
fuente