Remova subpastas vazias com PHP

Estou trabalhando em uma function PHP que irá remover de forma recursiva todas as subpastas que não contêm arquivos a partir de um determinado caminho absoluto.

Aqui está o código desenvolvido até agora:

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

De acordo com os meus testes, esta function funciona, embora eu fiquei muito satisfeito em ver quaisquer ideias para o código de melhor desempenho.

Se você tiver uma pasta vazia dentro da pasta vazia dentro da pasta vazia, você precisará percorrer TODAS as pastas três vezes. Tudo isso, porque você vai em largura primeiro – teste a pasta ANTES de testar seus filhos. Em vez disso, você deve entrar em pastas infantis antes de testar se o pai está vazio, desta forma uma passagem será suficiente.

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

Por sinal, glob não retorna. e .. inputs.

Versão mais curta:

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

Está linha

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

Poderia ser tornado um pouco mais legível:

 $ret = $ret || $res; 

Ou se o PHP tem o operador bitwise:

 $ret |= $res; 

Você pode executar um comando unix para remover diretórios vazios.

exec (“localize $ starting_from_path -type d -empty -exec rmdir {} \; 2> / dev / null”);

Isso significaria problemas porque chamar RemoveEmptySubFolders algumas vezes provavelmente soletrava erros porque cada vez que você chama a function, as outras 2 funções são definidas novamente. Se eles já foram definidos, o PHP lançará um erro dizendo que uma function do mesmo nome já foi definida.

Em vez disso tente-o recursivamente:

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

Testado, funcionando bem. Windows 7 PHP 5.3.0 XAMPP

Você pode tentar isso.

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

Solução para Linux, usando a ferramenta de linha de comando, mas mais rápido e simples do que com PHP puro

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

Se você precisar de suporte do Windows, use PHP_OS constante e este one-liner

 for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"`enter code here