2009-10-31 13 views
34

Próbuję usunąć katalog z rmdir, ale otrzymałem komunikat "Directory not empty", ponieważ nadal ma w nim pliki.Jak usunąć katalog, który nie jest pusty?

Jaką funkcję mogę użyć do usunięcia katalogu zawierającego wszystkie pliki w nim zawarte?

+0

Możliwy duplikat [Jak mogę rekursywnie usunąć katalog i całą jego zawartość (pliki + sub dirs) w PHP?] (http://stackoverflow.com/questions/3338123/how-do-i-recursively-delete-a-directory-and-its-entire-contents-files-sub-dir) – MaxiWheat

Odpowiedz

78

Nie ma wbudowanej funkcji, aby to zrobić, ale zobacz komentarze na dole: http://us3.php.net/rmdir. Wielu komentujących opublikowało własne funkcje kasowania katalogów rekursywnych. Możesz wybrać z nich.

Oto 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: Można po prostu powołać rm -rf jeśli chcesz zachować rzeczy proste. To sprawia, że ​​twój skrypt jest uniksowy, więc strzeż się tego. Jeśli wybierzesz tę trasę, wypróbuję coś takiego:

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

Jeśli chodzi o PHP, ** zawsze ** sprawdź podręcznik online i komentarze. Generalnie gwarantuje to, że ktoś miał problem pierwszy i skomentował. –

+0

Wybrałem ten: $ path = "/ path/to/empty"; $ cmd = "rm -rf $ path"; '$ cmd'; Czy coś jest z tym nie tak? – zeckdude

+2

+1 dla escapeshellarg() dla bezpieczeństwa – namespaceform

5

Zawsze możesz spróbować użyć poleceń systemowych.

Jeżeli na użytkowania Linux: rm -rf /dir Jeśli na oknach użyć: rd c:\dir /S /Q

W poście powyżej (John Kugelman) Przypuszczam, że parser PHP zoptymalizuje że scandir w foreach ale po prostu wydaje się źle mi się mieć scandir w oświadczeniu o warunku foreach.
Można również wykonać dwie komendy array_shift, aby usunąć . i .. zamiast zawsze sprawdzać w pętli.

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

Oto co kiedyś:

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

Spróbuj następującą poręczną funkcję:

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

Dzięki tej funkcji, będzie można usunąć dowolny plik lub folder

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

Mój przypadek miał sporo trudnych katalogów (na mes zawierający znaki specjalne, zagnieżdżanie głębokie, itp.) oraz ukryte pliki, które powodowały błędy "Directory not empty" z innymi sugerowanymi rozwiązaniami. Ponieważ Unix Jedynym rozwiązaniem było nie do przyjęcia, testowałem aż dotarłem na następujące rozwiązanie (które sprawdziły się w moim przypadku):

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

Aby rozszerzyć zapotrzebowanie na preg_replace, było to konieczne, ponieważ niektóre katalogi (ze znakami specjalnymi) pomijałyby podkatalogi, które wyraźnie istniały. Znalazłem notatkę preg_replace z komentarza w php.net dokumentacji dla glob(), gdzie ktoś inny walczył godzinami z tym samym problemem. –

+0

Jest to jedyny, który może rozwiązać mój problem również +1, dzięki – Franco

Powiązane problemy