Удалить пустые папки с PHP
Я работаю над функцией 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 ответов
Если у вас есть пустая папка в пустой папке в пустой папке, вам нужно будет три раза перебирать все папки. Все это, потому что вы идете в ширину первой тестовой папки перед тестированием ее детей. Вместо этого вы должны перейти в дочерние папки перед тестированием, если родитель пуст, таким образом, одного прохода будет достаточно.
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;
}
кстати, Глоб не возвращает . и.. вступления.
более короткая версия:
function RemoveEmptySubFolders($path)
{
$empty=true;
foreach (glob($path.DIRECTORY_SEPARATOR."*") as $file)
{
$empty &= is_dir($file) && RemoveEmptySubFolders($file);
}
return $empty && rmdir($path);
}
эта строка
$ret = $ret ? $ret : $res;
можно сделать немного более читаемым:
$ret = $ret || $res;
или если PHP имеет побитовый оператор:
$ret |= $res;
вы можете выполнить команду Unix для удаления пустых каталогов.
exec ("найти $starting_from_path-тип d-empty-exec rmdir {} \; 2>/dev / null");
это будет означать проблемы, потому что вызов 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
вы можете попробовать это.
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);
}
}
}
}
решение для 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