Рекурсивная функция удаления каталога для PHP?
Я использую PHP для перемещения содержимого подпапки изображений
GalleryName/изображения/
в другую папку. После перемещения мне нужно удалить каталог GalleryName и все остальное внутри него.
Я знаю, что rmdir()
не будет работать, если каталог не пуст. Я потратил некоторое время, пытаясь построить рекурсивную функцию для scandir()
, начиная с вершины, а затем unlink()
, если это файл и scandir()
, если это каталог, а затем rmdir()
каждый пустой каталог, когда я иду.
Пока это не работает правильно, и я начал думать - - это не смехотворно простая функция, которую должен делать PHP? Удаление каталога?
Так что-то мне не хватает? Или есть, по крайней мере, проверенная функция, которую люди используют для этого действия?
Любая помощь будет оценена.
PS Я доверяю вам всем здесь больше, чем комментарии на сайте php.net - там есть сотни функций, но мне интересно услышать, если кто-то из вас рекомендует его другим.
Ответы
Ответ 1
Как насчет этого?
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);
Ответ 2
Это рекурсивная функция, которую я создал/модифицировал и, наконец, кажется, работает. Надеюсь, в этом нет ничего слишком опасного.
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);
}
Ответ 3
Если сервер приложения работает под управлением linux, просто используйте функцию shell_exec() и предоставьте ей команду rm -R, например:
$realPath = realpath($dir_path);
if($realPath === FALSE){
throw new \Exception('Directory does not exist');
}
shell_exec("rm ". escapeshellarg($realPath) ." -R");
Объяснение:
Удаляет указанный каталог рекурсивно, только если путь существует, и экранирует путь, так что его можно использовать только в качестве аргумента оболочки, чтобы избежать внедрения команды оболочки.
Если вы не используете escapeshellarg
можно выполнить команды, escapeshellarg
каталог, который будет удален после команды.
Ответ 4
Я адаптировал функцию, которая обрабатывает скрытые файлы 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);
}
Ответ 5
Существует еще один поток с большим количеством примеров:
Как я могу рекурсивно удалить каталог и все его содержимое (файлы + поддиректории) в PHP?
Если вы используете Yii, вы можете оставить его в рамке:
CFileHelper::removeDirectory($my_directory);
Ответ 6
Я предпочитаю усиленный метод, полученный на страницах справки 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));
}
причины моего решения:
- меньше кода
- скорость
- сохранить его простым.
Ответ 7
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);
}
}