web-dev-qa-db-fra.com

Supprimer le répertoire contenant les fichiers?

Je me demande quel est le moyen le plus simple de supprimer un répertoire contenant tous ses fichiers.

J'utilise rmdir(PATH . '/' . $value); pour supprimer un dossier. Cependant, s'il contient des fichiers, je ne peux simplement pas le supprimer.

199
matt

Il y a au moins deux options disponibles de nos jours.

  1. Avant de supprimer le dossier, supprimez tous ses fichiers et dossiers (et cela signifie récursivité!). Voici un exemple:

    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. Et si vous utilisez 5.2+, vous pouvez utiliser un RecursiveIterator pour le faire sans avoir à faire la récursivité vous-même:

    $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);
    
316
alcuadrado

J'utilise généralement cela pour supprimer tous les fichiers d'un dossier:

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

Et alors tu peux faire

rmdir($dirname);
165
user3033886

quel est le moyen le plus simple de supprimer un répertoire contenant tous ses fichiers?

system("rm -rf ".escapeshellarg($dir));
72
Your Common Sense

Fonction courte qui fait le travail:

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

Je l'utilise dans un cours d'utilitaire comme ceci:

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

Un grand pouvoir entraîne une grande responsabilité : Lorsque vous appelez cette fonction avec une valeur vide, elle supprimera les fichiers commençant par la racine (/). En guise de sauvegarde, vous pouvez vérifier si le chemin est vide:

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

Ceci est une version plus courte fonctionne très bien pour moi

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);
    }
}
18
Playnox

Comme indiqué dans la plupart des commentaires votés sur la page de manuel PHP à propos de rmdir() (voir http://php.net/manual/es/function.rmdir.php ), la fonction glob() ne renvoie pas les fichiers cachés. scandir() est fourni à titre d'alternative permettant de résoudre ce problème.

L'algorithme décrit ici (qui a fonctionné comme un charme dans mon cas) est:

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

Vous pouvez utiliser le système de fichiers de Symfony ( code ):

// composer require symfony/filesystem

use Symfony\Component\Filesystem\Filesystem;

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

Cependant, je ne pouvais pas supprimer certaines structures de répertoires complexes avec cette méthode, vous devez donc d'abord l'essayer pour vous assurer qu'elle fonctionne correctement.


Je pourrais supprimer cette structure de répertoire en utilisant une implémentation spécifique à Windows:

$dir = strtr($dir, '/', '\\');
// quotes are important, otherwise one could
// delete "foo" instead of "foo bar"
system('RMDIR /S /Q "'.$dir.'"');


Et juste pour être complet, voici un de mes vieux codes:

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);
}
10
Gras Double

Vous avez ici une récursivité simple et agréable pour supprimer tous les fichiers du répertoire source, y compris ce répertoire:

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

}

La fonction est basée sur la récursivité réalisée pour la copie du répertoire. Vous pouvez trouver cette fonction ici: Copier tout le contenu d’un répertoire dans un autre en utilisant php

7
Tommz

La fonction Glob ne renvoie pas les fichiers cachés, donc scandir peut être plus utile lorsque vous essayez de supprimer de manière récursive un arbre.

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

Et ça:

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);
}
3
adrian

Je préfère cela car il retourne toujours TRUE quand il réussit et FALSE quand il échoue, et empêche également un bug où un chemin vide pourrait essayer de tout supprimer 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);
}
3
Matt Connolly

Utiliser DirectoryIterator est l'équivalent d'une réponse précédente…

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);
}
2
Alan Trewartha

La meilleure solution pour moi

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

code:

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

p.s. RAPPELLES TOI! 
ne passez pas de valeurs vides à un annuaire en supprimant des fonctions !!! (sauvegardez-les toujours, sinon un jour, vous pourriez avoir une catastrophe!)

2
T.Todua

Je souhaite développer la réponse de @alcuadrado avec le commentaire de @Vijit pour la gestion des liens symboliques. Tout d'abord, utilisez getRealPath (). Mais ensuite, si vous avez des liens symboliques qui sont des dossiers, cela échouera car il essaiera d'appeler rmdir sur un lien - vous aurez donc besoin d'une vérification supplémentaire.

$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);
2
user701152

Vous pouvez essayer comme suit:

/*
 * 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);
        }
    }
}
2
Bablu Ahmed

Peu de modifications du code d'alcuadrado - glob ne voit pas les fichiers portant le nom de points comme .htaccess, aussi j'utilise scandir et le script se supprime lui-même - cochez __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);
}
2
karma_police

Voici la solution qui fonctionne parfaitement:

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;
}
1
Tarik

Quelque chose comme ça?

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

2 cents à ajouter à CETTE réponse ci-dessus, ce qui est excellent BTW

Une fois que votre fonction glob (ou similaire) a analysé/lu le répertoire, ajoutez une condition pour vérifier que la réponse n'est pas vide ou un avertissement invalid argument supplied for foreach() sera émis. Alors...

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

Ma fonction complète (en tant que méthode d'objet):

    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()
1
Phil Meadows

Celui-ci fonctionne pour moi:

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

Pour les fenêtres:

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

Et ça? 

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

Référence: https://paulund.co.uk/php-delete-directory-and-files-in-directory

0
Mohamad Hamouday

Vous pouvez copier les YII aides

$ directory (string) - à supprimer récursivement.

$ options (array) - pour la suppression du répertoire. Les options valides sont: traverseSymlinks: boolean, si les liens symboliques vers les répertoires doivent également être parcourus. La valeur par défaut est false, ce qui signifie que le contenu du répertoire lié par un lien symbolique ne sera pas supprimé. Seul le lien symbolique serait supprimé dans ce cas par défaut.

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);
    }
}
0
José Veríssimo

Si vous n'êtes pas sûr, le chemin donné étant un répertoire ou un fichier, vous pouvez utiliser cette fonction pour supprimer le chemin.

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

Avez-vous essayé le code obove de php.net

Travaille bien pour moi

0
Gaurang

Exemple pour le serveur Linux: exec('rm -f -r ' . $cache_folder . '/*');

0
realmag777

Comme la solution de Playnox, mais avec l'élégant et intégré 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!');
  }
 }
0
Matthew Slyman

Simple et facile...

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

Je ne me souviens pas d'où j'ai copié cette fonction, mais on dirait qu'elle n'est pas répertoriée et qu'elle fonctionne pour moi

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);
    }
}
0
dav

vous pouvez essayer cette simple ligne de code de 12 lignes pour supprimer des dossiers ou des dossiers de dossiers ... codage heureux ...;) :)

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);
    }
}
0
Adeel Ahmed