Question

I have an directory tree which has been passed to array.

I would like to there empty folders inside this array.

How can I determine empty folders like /wp-content/uploads/2014/02/ and /wp-content/uploads/2014/. How can I delete them recursively.

Here is my array

array (
  0 => './do-update.php',
  5 => './wp-config.php',
  6 => './wp-content/',
  7 => './wp-content/uploads/',
  8 => './wp-content/uploads/2013/',
  9 => './wp-content/uploads/2013/05/',
  10 => './wp-content/uploads/2013/05/kabeduvarkad-1024x768.jpg',
  26 => './wp-content/uploads/2013/05/kabeduvarkad2.jpg',
  27 => './wp-content/uploads/2013/10/',
  28 => './wp-content/uploads/2014/',
  29 => './wp-content/uploads/2014/02/',
  30 => './wp-content/uploads/de.php',
  31 => './wp-update.tar.gz',
  32 => './wp-update/',
  33 => './wp-update/wp-update.tar',
)

Thank you very much to Andresch Serj for him effords. Who wants to delete empty folders recursively with performance, you can use this solution.

function list_directory($dir) {
   $file_list = array();
   $stack[] = $dir;

   while ($stack) {
        $current_dir = array_pop($stack);
        if ($dh = opendir($current_dir)){
            while (($file = readdir($dh)) !== false) {
                if ($file !== '.' AND $file !== '..') {
                    $current_file = "{$current_dir}/{$file}";
                    $report = array();
                    if (is_file($current_file)) {
                        $file_list[] = "{$current_dir}/{$file}";
                    } elseif (is_dir($current_file)) {
                        $stack[] = $current_file;
                        $file_list[] = "{$current_dir}/{$file}/";
                    }
                }
            }
        }
    }
    sort($file_list, SORT_LOCALE_STRING);
    return $file_list;
}

function remove_emptyfolders($array_filelist){
    $files = array();
    $folders = array();
    foreach($array_filelist as $path){
        // better performance for is_dir function
        if ($path[strlen($path)-1] == '/'){ // check for last character if it is / which is a folder.
            $folders[] = $path;
        }
        else{
            $files[] = $path;
        }
    }

    // bos olmayan klasorleri buluyoruz.
    // eger klasor ismi dosya isimlerinin icerisinde gecmiyorsa bos demektir? right?
    $folders_notempty = array();
    foreach($files as $file){
        foreach($folders as $folder){
            if(strpos($file,$folder) !== false){
                // dublicate olmasin diye key isimlerinin ismine yazdırdık.
                $folders_notempty[$folder] = $folder;
            }
        }
    }

    // bos olmayanla klasorleri, digerlerinden cikariyoruz.
    $folders_empty = array();
    foreach($folders as $folder){
        // eger bos olmayanlarin icerisinde bu dosya yoksa
        if(!in_array($folder, $folders_notempty)){
            $folders_empty[] = $folder;
        }
    }

    // once en uzaktan silmeye baslamaliyiz. kisaca tersten.
    $folders_empty = array_reverse($folders_empty);
    $folders_deleted = array();

    foreach($folders_empty as $k){
        try{
            $folders_deleted[$k] = 'NOT Succesfull';
            if(rmdir($k)){ $folders_deleted[$k] = 'Deleted'; continue; }
            chmod($k, 0777); 
            if(rmdir($k)){ $folders_deleted[$k] = 'Deleted after chmod'; }
        }catch (Exception $e) {
            print_r($e);
        }
    }

    return $folders_deleted;

}

$files = list_directory(getcwd());
//print_r($files);
$files_deleted = remove_emptyfolders($files);

print_r($files_deleted);
Was it helpful?

Solution

Simply iterate over your array using foreach.

foreach ($filesArray as $file) {

Then for each file, check if it is a folder using is_dir like this

if (is_dir ($file)) {

If it is a folder/directory, read the directory, for instanse using scandir.

$directoryContent = scandir($file);

If the result of scandir is empty, you have an empty folder that you can delete with unlink.

if (count($directoryContent) <= 2) { // checkig if there is moire than . and ..
  unlink($file);

If you have trouble with unlink, you may have to set file permissions accordingly.

If instead you need a function that recursively deletes empty subfolders given some paht, you should consider reading the SO question that was linkes in the comments.

EDIT

After taking into consideration your comments, what you do want is a function that deletes parent folders as well. So for a geiven level1/level2/level3 where level3 is empty and the only folder/file in level2 you want level2 to be deleted as well.

So from your example array, you want ./wp-content/uploads/2014/ deleted and not just ./wp-content/uploads/2014/10, but only if ./wp-content/uploads/2014/10 has no content or subfolders with content.

So how to do that?

Simle: Extend your check for weather that folder is empty. If it is empty, manipoulate the given file/path string to get the parent folder. By now you should outsource this to a recursive functions indeed.

function doesDirectoryOnlyContainEmptyFolders($path) {
  if(is_dir($path) {
    $directoryContent = scandir($path);
    if (count($directoryContent) <= 2) {
      return true;
    }
    else {
      foreach ($directoryContent as $subPath) {
        if($filePath !== '.' && $filePath !== '..' && !doesDirectoryOnlyContainEmptyFolders($subPath)) {
          return false;
        }
      }
      return true;
    }
  }
  return false;
}

So this function checks recursively if a path has only empty folders or folders containing empty folders - recursively. Now you want to check your paths and maybe delete them, recursively downwards and upwards.

function deleteEmptyFoldersRecursivelyUpAndDown($path) {
  if (is_dir($path)) {
    if(doesDirectoryOnlyContainEmptyFolders($path)) {
      unlink($path);
      $parentFolder = substr($path, 0, strripos ($path, '/'));
      deleteEmptyFoldersRecursivelyUpAndDown($parentFolder);
    }
    else {
      $directoryContent = scandir($path);
      foreach ($directoryContent as $subPath) {
        deleteEmptyFoldersRecursivelyUpAndDown($subPath);
      }
    }
  }
}

If the given path is a directory, we check if it is empty using our recursive function. If it is, we delete it and recursively check the parent directory. If it is not, we iterate over its content to find empty folders, again calling the function itself recursively.

With these two function you have all you need. Simply iterate over your path array and use deleteEmptyFoldersRecursivelyUpAndDownon all entries. If they are faulty, you'll manage to debug them i presume.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top