Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove empty subfolders with PHP

Tags:

directory

php

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.

like image 792
Dmitry Letano Avatar asked Dec 02 '09 15:12

Dmitry Letano


4 Answers

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);
    }
like image 57
yu_sha Avatar answered Oct 11 '22 13:10

yu_sha


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;
like image 44
Tom Ritter Avatar answered Oct 11 '22 12:10

Tom Ritter


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);
      }
    }
  }
}
like image 45
Mike luc Avatar answered Oct 11 '22 13:10

Mike luc


You can execute a unix command to remove empty directories.

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

like image 44
grigb Avatar answered Oct 11 '22 12:10

grigb