Рекурсивная функция удаления каталогов для PHP? - PullRequest
26 голосов
/ 10 сентября 2009

Я использую PHP для перемещения содержимого подпапки с изображениями

GalleryName / изображения /

в другую папку. После переезда мне нужно удалить каталог GalleryName и все остальное внутри него .

Я знаю, что rmdir() не будет работать, если каталог не пуст. Я потратил некоторое время, пытаясь построить рекурсивную функцию для scandir(), начиная с вершины, а затем unlink(), если это файл, и scandir(), если это каталог, а затем rmdir() каждый пустой каталог по мере продвижения.

Пока что он работает не совсем правильно, и я начал думать - разве это не смехотворно простая функция, которую должен уметь делать PHP? Удаление каталога?

Так я что-то упустил? Или есть хотя бы проверенная функция, которую люди используют для этого действия?

Буду признателен за любую помощь.

PS Я доверяю всем вам здесь больше, чем комментариям на сайте php.net - там есть сотни функций, но мне интересно услышать, если кто-то из вас порекомендует одну из них другим.

Ответы [ 7 ]

87 голосов
/ 27 февраля 2013

А как насчет этого вопроса?

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);
14 голосов
/ 11 сентября 2009

Это рекурсивная функция, которую я создал / модифицировал, и, похоже, она наконец работает. Надеюсь, в этом нет ничего слишком опасного.

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); 
} 
2 голосов
/ 29 декабря 2013

Если на сервере приложения работает linux, просто используйте функцию shell_exec () и предоставьте ей команду rm -R, например:

    $result = realpath($dir_path);

    if($result === FALSE){
         throw new \Exception('Directory does not exist');
    }

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

Пояснение:

Функция запускает вставленную команду непосредственно в linux. Это точно то же самое, что запустить команду в терминале Linux.

Команда rm удаляет файл или каталог, переданный в $dir_path, а опция -R сообщает система, чтобы запустить его рекурсивно.

0 голосов
/ 24 апреля 2018
public static function rrmdir($dir)
{
    if (is_dir($dir)) {
        $files = scandir($dir);
        foreach ($files as $file) {
            if ($file != "." && $file != "..") {
                if (filetype($dir . "/" . $file) == "dir")
                    self::rrmdir($dir . "/" . $file);
                else
                    unlink($dir . "/" . $file);
            }
        }
        reset($files);
        rmdir($dir);
    }
}
0 голосов
/ 22 апреля 2015

Я предпочитаю расширенный метод, полученный из страниц помощи php 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));
}

причины моего решения:

  • меньше кода
  • Скорость
  • будь проще
0 голосов
/ 05 января 2014

Здесь есть еще одна тема с большим количеством примеров: Как рекурсивно удалить каталог и все его содержимое (файлы + вложенные каталоги) в PHP?

Если вы используете Yii, вы можете оставить это для фреймворка:

CFileHelper::removeDirectory($my_directory);
0 голосов
/ 26 декабря 2012

Я адаптировал функцию, которая обрабатывает скрытые файлы Unix с префиксом точки и использует 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...