I am working on a PHP function that will recursively remove all sub-folders that contain no files starting from a given absolute path.
Here is the code developed so far:
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)) {}
}
As per my tests this function works, though I would be very delighted to see any ideas for better performing code.
If you have empty folder within empty folder within empty folder, you'll need to loop through ALL folders three times. All this, because you go breadth first - test folder BEFORE testing its children. Instead, you should go into child folders before testing if parent is empty, this way one pass will be sufficient.
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;
}
By the way, glob does not return . and .. entries.
Shorter version:
function RemoveEmptySubFolders($path)
{
$empty=true;
foreach (glob($path.DIRECTORY_SEPARATOR."*") as $file)
{
$empty &= is_dir($file) && RemoveEmptySubFolders($file);
}
return $empty && rmdir($path);
}
To check hidden files i updated return statement line
function RemoveEmptySubFolders($path)
{
$empty = true;
foreach (glob($path . DIRECTORY_SEPARATOR . "*") as $file) {
$empty &= is_dir($file) && RemoveEmptySubFolders($file);
}
return $empty && (is_readable($path) && count(scandir($path)) == 2) && rmdir($path);
}
This line
$ret = $ret ? $ret : $res;
Could be made a little more readable:
$ret = $ret || $res;
Or if PHP has the bitwise operator:
$ret |= $res;
You can try this.
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);
}
}
}
}
You can execute a unix command to remove empty directories.
exec("find $starting_from_path -type d -empty -exec rmdir {} \; 2>/dev/null");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With