Как удалить каталог, который не является пустым? - PullRequest
42 голосов
/ 31 октября 2009

Я пытаюсь удалить каталог с rmdir, но я получил сообщение «Каталог не пуст», потому что в нем все еще есть файлы.

Какую функцию я могу использовать для удаления каталога со всеми файлами в нем?

Ответы [ 10 ]

98 голосов
/ 31 октября 2009

Для этого нет встроенной функции, но см. Комментарии внизу http://us3.php.net/rmdir. Ряд комментаторов разместили свои собственные рекурсивные функции удаления каталогов. Вы можете выбрать из них.

Вот тот, который выглядит прилично :

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

Редактировать: Вы можете просто вызвать rm -rf, если хотите, чтобы все было просто. Это делает ваш скрипт только для UNIX, так что будьте осторожны. Если вы пойдете по этому пути, я бы попробовал что-то вроде:

function deleteDirectory($dir) {
    system('rm -rf ' . escapeshellarg($dir), $retval);
    return $retval == 0; // UNIX commands return zero on success
}
7 голосов
/ 29 июля 2014
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);
 }
}
6 голосов
/ 31 октября 2009

Вы всегда можете попробовать использовать системные команды.

Если в Linux используется: rm -rf /dir Если на окнах использовать: rd c:\dir /S /Q

В посте выше ( Джон Кугельман ) я полагаю, что синтаксический анализатор PHP оптимизирует этот scandir в foreach, но мне просто неправильно указывать scandir в условии foreach.
Вы также можете просто сделать две команды array_shift, чтобы удалить . и .., вместо того, чтобы всегда проверять в цикле.

3 голосов
/ 09 мая 2016

В моем случае было немало хитрых каталогов (имена, содержащие специальные символы, глубокое вложение и т. Д.) И скрытых файлов, которые приводили к ошибкам «Каталог не пуст» с другими предлагаемыми решениями. Поскольку решение только для Unix было неприемлемым, я тестировал, пока не пришел к следующему решению (которое хорошо работало в моем случае):

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;
}
3 голосов
/ 06 апреля 2016

Вот что я использовал:

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);
2 голосов
/ 25 января 2019

Я не пришел, чтобы удалить папку, потому что PHP сказал мне, что она не пустая. Но это было. Функция Намана была хорошим решением для завершения моей. Вот что я использую:

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

function deleteDir($dir) {

    foreach(glob($dir . '/' . '*') as $file) {
        if(is_dir($file)){


            deleteDir($file);
        } else {

          unlink($file);
        }
    }
    emptyDir($dir);
    rmdir($dir);
}

Итак, чтобы удалить каталог и рекурсивно его содержимое:

deleteDir($dir);
2 голосов
/ 21 марта 2018

Не могу придумать более простой и эффективный способ сделать это, чем этот

<?php
    $dirname = './myfolder';
    if (is_dir($dirname)) {
        $dir = new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS);
        foreach (new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST ) as $filename => $file) {
            if (is_file($filename))
                unlink($filename);
            else
                rmdir($filename);
        }
        rmdir($dirname); // Now remove myfolder
    }
?>
1 голос
/ 19 февраля 2019

С http://php.net/manual/en/function.rmdir.php#91797

Функция Glob не возвращает скрытые файлы, поэтому scandir может быть более полезен при попытке рекурсивного удаления дерева.

<?php 
public static function delTree($dir) { 
   $files = array_diff(scandir($dir), array('.','..')); 
    foreach ($files as $file) { 
      (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file"); 
    } 
    return rmdir($dir); 
  } 
?>
1 голос
/ 21 апреля 2016

С помощью этой функции вы сможете удалить любой файл или папку

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 голос
/ 08 апреля 2016

Попробуйте следующую полезную функцию:

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