递归查找空文件夹并递归删除它们

时间:2014-05-05 09:07:35

标签: php recursion unlink is-empty

我有一个已传递给数组的目录树。

我想在这个数组中有空文件夹。

如何确定/wp-content/uploads/2014/02//wp-content/uploads/2014/等空文件夹。 如何递归删除它们。

这是我的数组

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',
)

非常感谢Andresch Serj为他提供的服务。 谁想要以性能递归删除空文件夹,您可以使用此解决方案。

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);

1 个答案:

答案 0 :(得分:0)

使用foreach简单地遍历数组。

foreach ($filesArray as $file) {

然后对于每个文件,检查它是否是使用is_dir这样的文件夹

if (is_dir ($file)) {

如果是文件夹/目录,请使用scandir读取目录,以获取实例。

$directoryContent = scandir($file);

如果scandir的结果为空,则您有一个空文件夹,可以使用unlink删除。

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

如果您遇到unlink问题,则可能需要相应地设置文件权限。

如果您需要一个以递归方式递归删除空子文件夹的函数,您应该考虑阅读SO question that was linkes in the comments

修改

考虑到你的评论后,你想要的是一个删除父文件夹的功能。因此,对于其中level1/level2/level3为空的geiven level3以及level2中唯一要删除level2的文件夹/文件。

因此,从您的示例数组中,您希望删除./wp-content/uploads/2014/而不仅仅是./wp-content/uploads/2014/10,但仅当./wp-content/uploads/2014/10没有内容或子文件夹时才会删除。

那怎么做?

Simle:扩展您对该文件夹为空的天气的检查。如果为空,则操作给定的文件/路径字符串以获取父文件夹。到目前为止,您应该将其外包给递归函数。

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;
}

因此,如果路径只有空文件夹或包含空文件夹的文件夹,则递归检查此函数。 现在,您想要检查路径,并可能以递归方式向下和向上删除它们。

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);
      }
    }
  }
}

如果给定路径是目录,我们使用递归函数检查它是否为为空。 如果是,我们删除它并递归检查父目录。 如果不是,我们迭代其内容以找到空文件夹,再次以递归方式调用函数。

通过这两项功能,您可以获得所需的一切。只需遍历路径数组并在所有条目上使用deleteEmptyFoldersRecursivelyUpAndDown。如果它们有问题,你就可以设法调试它们。