Удалить пустые подпапки с помощью PHP - PullRequest
6 голосов
/ 02 декабря 2009

Я работаю над функцией PHP, которая будет рекурсивно удалять все подпапки, не содержащие файлов, начиная с заданного абсолютного пути.

Вот код, разработанный на данный момент:

function RemoveEmptySubFolders($starting_from_path) {

    // Returns true if the folder contains no files
    function IsEmptyFolder($folder) {
        return (count(array_diff(glob($folder.DIRECTORY_SEPARATOR."*"), Array(".", ".."))) == 0);
    }

    // Cycles thorugh the subfolders of $from_path and
    // returns true if at least one empty folder has been removed
    function DoRemoveEmptyFolders($from_path) {
        if(IsEmptyFolder($from_path)) {
            rmdir($from_path);
            return true;
        }
        else {
            $Dirs = glob($from_path.DIRECTORY_SEPARATOR."*", GLOB_ONLYDIR);
            $ret = false;
            foreach($Dirs as $path) {
                $res = DoRemoveEmptyFolders($path);
                $ret = $ret ? $ret : $res;
            }
            return $ret;
        }
    }

    while (DoRemoveEmptyFolders($starting_from_path)) {}
}

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

Ответы [ 6 ]

22 голосов
/ 02 декабря 2009

Если у вас есть пустая папка в пустой папке внутри пустой папки, вам нужно будет три раза просмотреть все папки. Все это потому, что вы идете в ширину - тестируйте папку ДО тестирования ее дочерних элементов. Вместо этого вам следует перейти в дочерние папки перед проверкой, если родительский элемент пуст, так что одного прохода будет достаточно.

function RemoveEmptySubFolders($path)
{
  $empty=true;
  foreach (glob($path.DIRECTORY_SEPARATOR."*") as $file)
  {
     if (is_dir($file))
     {
        if (!RemoveEmptySubFolders($file)) $empty=false;
     }
     else
     {
        $empty=false;
     }
  }
  if ($empty) rmdir($path);
  return $empty;
}

Кстати, glob не возвращается. и .. записи.

Укороченная версия:

function RemoveEmptySubFolders($path)
{
  $empty=true;
  foreach (glob($path.DIRECTORY_SEPARATOR."*") as $file)
  {
     $empty &= is_dir($file) && RemoveEmptySubFolders($file);
  }
  return $empty && rmdir($path);
}
1 голос
/ 30 августа 2013

Вы можете выполнить команду unix для удаления пустых каталогов.

exec ("find $ initial_from_path -type d -empty -exec rmdir {} \; 2> / dev / null");

1 голос
/ 02 декабря 2009

Эта строка

$ret = $ret ? $ret : $res;

Можно сделать немного более читабельным:

$ret = $ret || $res;

Или, если PHP имеет побитовый оператор:

$ret |= $res;
0 голосов
/ 28 апреля 2014

Решение для Linux, использующее инструмент командной строки, но быстрее и проще, чем с чистым PHP

/**
 * Remove all empty subdirectories
 * @param string $dirPath path to base directory
 * @param bool $deleteBaseDir - Delete also basedir if it is empty
 */
public static function removeEmptyDirs($dirPath, $deleteBaseDir = false) {

    if (stristr($dirPath, "'")) {
        trigger_error('Disallowed character `Single quote` (\') in provided `$dirPath` parameter', E_USER_ERROR);
    }

    if (substr($dirPath, -1) != '/') {
        $dirPath .= '/';
    }

    $modif = $deleteBaseDir ? '' : '*';
    exec("find '".$dirPath."'".$modif." -empty -type d -delete", $out);
}

Если вам нужна поддержка Windows, используйте PHP_OS константу и этот однострочный

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"`enter code here
0 голосов
/ 08 апреля 2010

Вы можете попробовать это.

function removeEmptySubfolders($path){

  if(substr($path,-1)!= DIRECTORY_SEPARATOR){
    $path .= DIRECTORY_SEPARATOR;
  }
  $d2 = array('.','..');
  $dirs = array_diff(glob($path.'*', GLOB_ONLYDIR),$d2);
  foreach($dirs as $d){
    removeEmptySubfolders($d);
  }

  if(count(array_diff(glob($path.'*'),$d2))===0){
    $checkEmpSubDir = explode(DIRECTORY_SEPARATOR,$path);
    for($i=count($checkEmpSubDir)-1;$i>0;$i--){
      $path = substr(str_replace($checkEmpSubDir[$i],"",$path),0,-1);

      if(($files = @scandir($path)) && count($files) <= 2){
        rmdir($path);
      }
    }
  }
}
0 голосов
/ 02 декабря 2009

Это может вызвать проблемы, потому что вызов RemoveEmptySubFolders несколько раз может привести к ошибкам, потому что каждый раз, когда вы вызываете функцию, остальные 2 функции определяются снова. Если они уже определены, PHP выдаст ошибку, сообщив, что функция с таким же именем уже определена.

Вместо этого попробуйте это рекурсивно:

function removeEmptySubfolders($path){

  if(substr($path,-1)!= DIRECTORY_SEPARATOR){
    $path .= DIRECTORY_SEPARATOR;
  }
  $d2 = array('.','..');
  $dirs = array_diff(glob($path.'*', GLOB_ONLYDIR),$d2);
  foreach($dirs as $d){
     removeEmptySubfolders($d);
  }

  if(count(array_diff(glob($path.'*'),$d2))===0){
    rmdir($path);
  }

}

Проверено, работает хорошо. Windows 7 PHP 5.3.0 XAMPP

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...