web-dev-qa-db-fra.com

Comment puis-je supprimer un répertoire qui n'est pas vide?

J'essaie de supprimer un répertoire avec rmdir, mais j'ai reçu le message "Répertoire non vide", car il contient toujours des fichiers.

Quelle fonction puis-je utiliser pour supprimer un répertoire contenant tous les fichiers qu'il contient?

41
zeckdude

Il n’existe pas de fonction intégrée permettant de faire cela, mais consultez les commentaires au bas de http://us3.php.net/rmdir . Un certain nombre de commentateurs ont publié leurs propres fonctions de suppression de répertoire récursive. Vous pouvez faire votre choix parmi ceux-ci.

Voici celui qui a l'air décent :

function deleteDirectory($dir) {
    if (!file_exists($dir)) {
        return true;
    }

    if (!is_dir($dir)) {
        return unlink($dir);
    }

    foreach (scandir($dir) as $item) {
        if ($item == '.' || $item == '..') {
            continue;
        }

        if (!deleteDirectory($dir . DIRECTORY_SEPARATOR . $item)) {
            return false;
        }

    }

    return rmdir($dir);
}

Edit: Vous pouvez simplement appeler rm -rf si vous voulez garder les choses simples. Cela rend votre script uniquement sous UNIX, alors méfiez-vous de cela. Si vous y allez, j'essaierais quelque chose comme:

function deleteDirectory($dir) {
    system('rm -rf ' . escapeshellarg($dir), $retval);
    return $retval == 0; // UNIX commands return zero on success
}
95
John Kugelman

Vous pouvez toujours essayer d'utiliser des commandes système.

Si vous utilisez Linux, utilisez: rm -rf /dir Si vous utilisez Windows, utilisez: rd c:\dir /S /Q

Dans le message ci-dessus ( John Kugelman ), je suppose que l’analyseur PHP optimisera ce scandir dans le foreach, mais il me semble tout simplement faux que la variable scandir soit définie dans la condition foreach.
Vous pouvez également simplement exécuter deux commandes array_shift pour supprimer les . et .. au lieu de toujours vérifier la boucle. 

5
AntonioCS
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);
  }
}
4
Abhay

Ne peut pas penser à un moyen plus facile et plus efficace de le faire que cela

<?php
    $dirname = './myfolder';
    if (is_dir($dirname)) {
        $dir = new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS);
        foreach (new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST ) as $filename => $file) {
            if (is_file($filename))
                unlink($filename);
            else
                rmdir($filename);
        }
        rmdir($dirname); // Now remove myfolder
    }
?>
1
FatalError

Je ne suis pas arrivé à supprimer un dossier car PHP m'a dit qu'il n'était pas vide. Mais c'était. La fonction de Naman était la bonne solution pour compléter le mien. Alors voici ce que j'utilise:

function emptyDir($dir) {
    if (is_dir($dir)) {
        $scn = scandir($dir);
        foreach ($scn as $files) {
            if ($files !== '.') {
                if ($files !== '..') {
                    if (!is_dir($dir . '/' . $files)) {
                        unlink($dir . '/' . $files);
                    } else {
                        emptyDir($dir . '/' . $files);
                        rmdir($dir . '/' . $files);
                    }
                }
            }
        }
    }
}

function deleteDir($dir) {

    foreach(glob($dir . '/' . '*') as $file) {
        if(is_dir($file)){


            deleteDir($file);
        } else {

          unlink($file);
        }
    }
    emptyDir($dir);
    rmdir($dir);
}

Donc, pour supprimer un répertoire et récursivement son contenu: 

deleteDir($dir);
1
francoisV

Mon cas comportait quelques répertoires compliqués (noms contenant des caractères spéciaux, imbrication profonde, etc.) et des fichiers cachés générant des erreurs "Répertoire non vide" avec d'autres solutions suggérées. Comme une solution Unix seulement était inacceptable, j'ai testé jusqu'à arriver à la solution suivante (qui a bien fonctionné dans mon cas):

function removeDirectory($path) {
    // The preg_replace is necessary in order to traverse certain types of folder paths (such as /dir/[[dir2]]/dir3.abc#/)
    // The {,.}* with GLOB_BRACE is necessary to pull all hidden files (have to remove or get "Directory not empty" errors)
    $files = glob(preg_replace('/(\*|\?|\[)/', '[$1]', $path).'/{,.}*', GLOB_BRACE);
    foreach ($files as $file) {
        if ($file == $path.'/.' || $file == $path.'/..') { continue; } // skip special dir entries
        is_dir($file) ? removeDirectory($file) : unlink($file);
    }
    rmdir($path);
    return;
}
1
Brandon Elliott

Voici ce que j'ai utilisé:

function emptyDir($dir) {
    if (is_dir($dir)) {
        $scn = scandir($dir);
        foreach ($scn as $files) {
            if ($files !== '.') {
                if ($files !== '..') {
                    if (!is_dir($dir . '/' . $files)) {
                        unlink($dir . '/' . $files);
                    } else {
                        emptyDir($dir . '/' . $files);
                        rmdir($dir . '/' . $files);
                    }
                }
            }
        }
    }
}

$dir = 'link/to/your/dir';
emptyDir($dir);
rmdir($dir);
1
Naman

Avec cette fonction, vous pourrez supprimer n'importe quel fichier ou dossier

function deleteDir($dirPath)
{
    if (!is_dir($dirPath)) {
        if (file_exists($dirPath) !== false) {
            unlink($dirPath);
        }
        return;
    }

    if ($dirPath[strlen($dirPath) - 1] != '/') {
        $dirPath .= '/';
    }

    $files = glob($dirPath . '*', GLOB_MARK);
    foreach ($files as $file) {
        if (is_dir($file)) {
            deleteDir($file);
        } else {
            unlink($file);
        }
    }

    rmdir($dirPath);
}
0

Essayez la fonction pratique suivante:

/**
 * Removes directory and its contents
 *
 * @param string $path Path to the directory.
 */
function _delete_dir($path) {
  if (!is_dir($path)) {
    throw new InvalidArgumentException("$path must be a directory");
  }
  if (substr($path, strlen($path) - 1, 1) != DIRECTORY_SEPARATOR) {
    $path .= DIRECTORY_SEPARATOR;
  }
  $files = glob($path . '*', GLOB_MARK);
  foreach ($files as $file) {
    if (is_dir($file)) {
      _delete_dir($file);
    } else {
      unlink($file);
    }
  }
  rmdir($path);
}
0
kenorb

De http://php.net/manual/en/function.rmdir.php#91797

La fonction Glob ne renvoie pas les fichiers cachés. Par conséquent, 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); 
  } 
?>
0
Mykola Veriga