2009-10-31 20 views
34

Sto cercando di rimuovere una directory con rmdir, ma ho ricevuto il messaggio 'Directory non vuota', perché contiene ancora file.Come rimuovo una directory che non è vuota?

Quale funzione è possibile utilizzare per rimuovere una directory con tutti i file al suo interno?

+0

Eventuali duplicati di [Come posso ricorsivamente cancellare una directory e tutto il suo contenuto (file + sottodirectory) in PHP?] (http://stackoverflow.com/questions/3338123/how-do-i-recursively-delete-a-directory-and-its-entire-contents-files-sub-dir) – MaxiWheat

risposta

78

Non esiste alcuna funzione incorporata per eseguire questa operazione, ma vedere i commenti nella parte inferiore di http://us3.php.net/rmdir. Un certo numero di commentatori ha pubblicato le proprie funzioni di cancellazione delle directory ricorsive. Puoi scegliere tra quelli.

Ecco one that looks decent:

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: si può solo richiamare rm -rf se si vuole mantenere le cose semplici. Questo rende il tuo script solo per UNIX, quindi fai attenzione. Se segui questa strada, proverei qualcosa del tipo:

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

Quando si tratta di PHP, ** sempre ** controlla il manuale online e i commenti. È generalmente garantito che qualcuno ha avuto il problema prima e ha commentato lì. –

+0

Ho scelto questo: $ percorso = "/ percorso/a/vuoto"; $ cmd = "rm -rf $ percorso"; '$ cmd'; C'è qualcosa di sbagliato in questo? – zeckdude

+2

+1 per escapeshellarg() per sicurezza – namespaceform

5

Si può sempre provare a utilizzare i comandi di sistema.

Se sull'uso di Linux: rm -rf /dir Se su Windows Utilizzare: rd c:\dir /S /Q

Nel post di cui sopra (John Kugelman) Suppongo che il parser PHP ottimizzerà che scandir nel foreach ma sembra solo sbagliato per me avere la scandir nella dichiarazione di condizione foreach.
È anche possibile eseguire due comandi array_shift per rimuovere . e .. invece di effettuare sempre il check in.

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

Ecco quello che ho usato:

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

Prova la seguente funzione a portata di mano:

/** 
* 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

Con questa funzione, si sarà in grado di eliminare qualsiasi file o cartella

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

Il mio caso aveva alcune directory difficili (na mes contenente caratteri speciali, nidificazione profonda, ecc.) e file nascosti che hanno prodotto errori "Directory non vuota" con altre soluzioni suggerite. Dal momento che un Unix unica soluzione era inaccettabile, ho provato fino a quando sono arrivato alla soluzione di seguito (che ha funzionato bene nel mio caso):

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; 
} 
+0

Per espandere la necessità di preg_replace, era necessario perché alcune directory (con caratteri speciali) omettevano sottodirectory chiaramente esistenti. Ho trovato la nota preg_replace da un commento nel php.documentazione di rete per glob(), dove qualcun altro ha lottato per ore con lo stesso problema. –

+0

Questo è l'unico che potrebbe risolvere il mio problema anche +1, grazie – Franco

Problemi correlati