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
You can execute a unix command to remove empty directories.
exec("find $starting_from_path -type d -empty -exec rmdir {} \; 2>/dev/null");
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);
}
}
}
}
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;
This would spell trouble because calling RemoveEmptySubFolders
a few times would probably spell errors because each time you call the function, the other 2 functions are defined again. If they have already been defined, PHP will throw an error saying a function of the same name has already been defined.
Instead try it recursively:
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);
}
}
Tested, working nicely. Windows 7 PHP 5.3.0 XAMPP
Solution for Linux, using command line tool but faster and simpler than with pure 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);
}
If you need Windows support, use PHP_OS
constant and this one-liner
for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"`enter code here
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);
}