【问题标题】:How can I use PHP to check if a directory is empty?如何使用 PHP 检查目录是否为空?
【发布时间】:2011-11-21 19:14:06
【问题描述】:

我正在使用以下脚本来读取目录。如果目录中没有文件,它应该说是空的。问题是,它只是一直说目录是空的,即使里面有文件,反之亦然。

<?php
$pid = $_GET["prodref"];
$dir = '/assets/'.$pid.'/v';
$q   = (count(glob("$dir/*")) === 0) ? 'Empty' : 'Not empty';
    
if ($q=="Empty") 
    echo "the folder is empty"; 
else
    echo "the folder is NOT empty";
?>

【问题讨论】:

  • 这只是你的 if 语句中的一个错字。使用 ==(比较)而不是单个 =(分配)。

标签: php directory


【解决方案1】:

看来您需要scandir 而不是 glob,因为 glob 看不到 unix 隐藏文件。

<?php
$pid = basename($_GET["prodref"]); //let's sanitize it a bit
$dir = "/assets/$pid/v";

if (is_dir_empty($dir)) {
  echo "the folder is empty"; 
}else{
  echo "the folder is NOT empty";
}

function is_dir_empty($dir) {
  if (!is_readable($dir)) return null; 
  return (count(scandir($dir)) == 2);
}
?>

请注意,这段代码并不是效率的顶峰,因为不需要读取所有文件来判断目录是否为空。所以,更好的版本应该是

function dir_is_empty($dir) {
  $handle = opendir($dir);
  while (false !== ($entry = readdir($handle))) {
    if ($entry != "." && $entry != "..") {
      closedir($handle);
      return false;
    }
  }
  closedir($handle);
  return true;
}

顺便说一句,不要使用 words 来代替 boolean 值。后者的目的是告诉你某物是否为空。一个

a === b

表达式已经在编程语言方面返回EmptyNon Empty,分别为falsetrue - 因此,您可以在IF() 等控制结构中使用结果而无需任何中间值

【讨论】:

  • 我认为我们的代码都是错误的,因为我从文件夹中删除了所有文件,但它仍然说文件夹不为空......有没有办法检查隐藏文件,如 thumbs.db 等linux??
  • 我认为 FTP 文件夹是 .. 和 .文件中为空。如何检查并删除 .. 和 thumbs.db 等?
  • glob 不支持 linux 隐藏文件。如果你想要他们,你必须像在已删除的答案中那样寻求 openir 解决方案
  • 看来你需要 scandir 而不是 glob。
  • 创建测试环境。在脚本所在的同一文件夹中创建空目录。手动制作$dir = 'testfolder';。然后运行此代码。 debug 正在打印尽可能多的信息以查看问题所在。 $dir = 'testfolder';var_dump(scan_dir($dir)); 会告诉你这个目录里有什么
【解决方案2】:

我认为使用FilesystemIterator 应该是最快最简单的方法:

// PHP 5 >= 5.3.0
$iterator = new \FilesystemIterator($dir);
$isDirEmpty = !$iterator->valid();

或者在实例化时使用类成员访问:

// PHP 5 >= 5.4.0
$isDirEmpty = !(new \FilesystemIterator($dir))->valid();

这是可行的,因为新的FilesystemIterator 最初将指向文件夹中的第一个文件 - 如果文件夹中没有文件,valid() 将返回 false。 (参见文档here。)

正如 abdulmanov.ilmir 所指出的,在使用 FileSystemIterator 之前,可选择检查目录是否存在,否则会抛出 UnexpectedValueException

【讨论】:

  • 嗯...为这个感到刺痛。
  • 你应该考虑到如果$dir不存在那么就会抛出异常。
【解决方案3】:

我找到了一个快速的解决方案

<?php
  $dir = 'directory'; // dir path assign here
  echo (count(glob("$dir/*")) === 0) ? 'Empty' : 'Not empty';
?>

【讨论】:

  • 我在 php 5.2 中用于简单案例的解决方案。
  • 请注意 glob 看不到隐藏文件。包含即“.htaccess”的目录将被此代码视为空
【解决方案4】:

使用

if ($q == "Empty")

而不是

if ($q="Empty")

【讨论】:

    【解决方案5】:

    对于使用来自Standard PHP Library (SPL)RecursiveDirectoryIterator 的面向对象方法。

    <?php
    
    namespace My\Folder;
    
    use RecursiveDirectoryIterator;
    
    class FileHelper
    {
        /**
         * @param string $dir
         * @return bool
         */
        public static function isEmpty($dir)
        {
            $di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
            return iterator_count($di) === 0;
        }
    }
    

    无需在需要时创建FileHelper 的实例,您可以在任何需要的地方访问此静态方法,如下所示:

    FileHelper::isEmpty($dir);
    

    FileHelper 类可以使用其他有用的方法进行扩展,用于复制、删除、重命名等。

    不需要检查方法内目录的有效性,因为如果它无效,RecursiveDirectoryIterator 的构造函数将抛出一个足以覆盖该部分的UnexpectedValueException

    【讨论】:

      【解决方案6】:

      我用过:

      if(is_readable($dir)&&count(scandir($dir))==2) ... //then the dir is empty
      

      【讨论】:

        【解决方案7】:

        试试这个:

        <?php
        $dirPath = "Add your path here";
        
        $destdir = $dirPath;
        
        $handle = opendir($destdir);
        $c = 0;
        while ($file = readdir($handle)&& $c<3) {
            $c++;
        }
        
        if ($c>2) {
            print "Not empty";
        } else {
            print "Empty";
        } 
        
        ?>
        

        【讨论】:

        • 谢谢!我写得很快,这是我在这里的第一篇文章@Piotr Nowicki
        • 当然,伙计,这只是我的公民义务 ;-) 欢迎来到 StackOverflow!
        【解决方案8】:

        可能是因为if 语句中的赋值运算符。

        变化:

        if ($q="Empty")
        

        收件人:

        if ($q=="Empty")
        

        【讨论】:

          【解决方案9】:

          这是一个非常古老的线程,但我想我会给我的 10 美分。其他解决方案对我不起作用。

          这是我的解决方案:

          function is_dir_empty($dir) {
              foreach (new DirectoryIterator($dir) as $fileInfo) {
                  if($fileInfo->isDot()) continue;
                  return false;
              }
              return true;
          }
          

          短而甜。像魅力一样工作。

          【讨论】:

            【解决方案10】:

            @你的常识

            我认为您的性能示例使用严格比较可能会更高效:

            function is_dir_empty($dir) {
              if (!is_readable($dir)) return null; 
              $handle = opendir($dir);
              while (false !== ($entry = readdir($handle))) {
                if ($entry !== '.' && $entry !== '..') { // <-- better use strict comparison here
                  closedir($handle); // <-- always clean up! Close the directory stream
                  return false;
                }
              }
              closedir($handle); // <-- always clean up! Close the directory stream
              return true;
            }
            

            【讨论】:

            • 关于清理的好点:return false 案子没有解决它;-)
            • @BeatChristen 谢谢提示!修好了。
            • 我不明白的是为什么你说与“。”比较时最好使用严格比较。和 ”..”。 readdir() 函数将始终返回一个字符串(或 false),所以我不明白这一点。我还想补充一点,在你自己之后清理确实总是一个好主意,人们会认为当 $handle 变量超出范围时返回后,closeir() 会自动发生,但我只是写了一个小测试程序,但事实并非如此。这很奇怪,因为其他东西,比如羊群确实会自动发生。
            • @AndréFiedler 你是一个天才、才华横溢和负责任的人。在所有其他答案中,他们首先计算文件总数,然后检查 count > 0。但如果一个目录甚至包含一个文件,则它不为空。
            【解决方案11】:

            函数count 在大阵列上的使用可能很慢。 isset 越来越快

            这将在 PHP >= 5.4.0 上正常工作(请参阅变更日志 here

            function dir_is_empty($path){ //$path is realpath or relative path
            
                $d = scandir($path, SCANDIR_SORT_NONE ); // get dir, without sorting improve performace (see Comment below). 
            
                if ($d){
            
                    // avoid "count($d)", much faster on big array. 
                    // Index 2 means that there is a third element after ".." and "."
            
                    return !isset($d[2]); 
                }
            
                return false; // or throw an error
            }
            

            否则,使用@Your Common Sense 解决方案最好避免在 RAM 上加载文件列表

            感谢并投票给@soger,以使用SCANDIR_SORT_NONE 选项改进此答案。

            【讨论】:

            • 只要我们担心性能,您可能还想添加 SCANDIR_SORT_NONE 参数。
            【解决方案12】:

            只需像这样更正您的代码:

            <?php
                $pid = $_GET["prodref"];
                $dir = '/assets/'.$pid.'/v';
                $q = count(glob("$dir/*")) == 0;
            
                if ($q) {
                    echo "the folder is empty"; 
                } else {
                    echo "the folder is NOT empty";
                }
            ?>
            

            【讨论】:

              【解决方案13】:

              即使是一个空目录也包含两个文件...,一个是指向当前目录的链接,第二个是指向父目录的链接。因此,您可以使用如下代码:

              $files = scandir("path to directory/");
              if(count($files) == 2) {
                //do something if empty
              }
              

              【讨论】:

              • 请在您的答案中添加一些解释,以便其他人可以从中学习
              【解决方案14】:

              我在我的 Wordpress CSV 2 POST 插件中使用此方法。

                  public function does_folder_contain_file_type( $path, $extension ){
                      $all_files  = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ) );
              
                      $html_files = new RegexIterator( $all_files, '/\.'.$extension.'/' );  
              
                      foreach( $html_files as $file) {
                          return true;// a file with $extension was found
                      }   
              
                  return false;// no files with our extension found
              }
              

              它通过特定的扩展名工作,但通过删除“new RegexIterator(”行。计数 $all_files。

                  public function does_folder_contain_file_type( $path, $extension ){
                      $all_files  = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ) );
              
                      return count( $all_files );
                  }
              

              【讨论】:

                【解决方案15】:

                我最近遇到了类似的问题,尽管最高票数的答案对我来说并没有真正起作用,因此,我不得不想出一个类似的解决方案。同样,这也可能不是解决问题的最有效方法,

                我创建了一个这样的函数

                function is_empty_dir($dir)
                   {
                       if (is_dir($dir))
                       {
                            $objects = scandir($dir);
                            foreach ($objects as $object)
                            {
                                if ($object != "." && $object != "..")
                                {
                                    if (filetype($dir."/".$object) == "dir")
                                    {
                                         return false;
                                    } else { 
                                        return false;
                                    }
                                }
                            }
                            reset($objects);
                            return true;
                       }
                

                并用它来检查空的字典,像这样

                if(is_empty_dir($path)){
                            rmdir($path);
                        }
                

                【讨论】:

                  【解决方案16】:

                  你可以用这个:

                  function isEmptyDir($dir)
                  {
                      return (($files = @scandir($dir)) && count($files) <= 2);
                  }
                  

                  【讨论】:

                    【解决方案17】:

                    第一个问题是什么时候目录是空的?在一个目录中有 2 个文件 '.'和 '..'。
                    在 Mac 上,旁边可能有文件“.DS_Store”。该文件是在将某种内容添加到目录时创建的。如果这 3 个文件在目录中,您可能会说该目录是空的。 所以要测试一个目录是否为空(不测试 $dir 是否是一个目录):

                    function isDirEmpty( $dir ) {
                      $count = 0;
                      foreach (new DirectoryIterator( $dir ) as $fileInfo) {
                         if ( $fileInfo->isDot() || $fileInfo->getBasename() == '.DS_Store' ) {
                            continue;
                         }
                         $count++;
                      }
                      return ($count === 0);
                    }
                    

                    【讨论】:

                      【解决方案18】:

                      @你的常识,@Enyby

                      您的代码的一些改进:

                      function dir_is_empty($dir) {
                          $handle = opendir($dir);
                          $result = true;
                          while (false !== ($entry = readdir($handle))) {
                              if ($entry != "." && $entry != "..") {
                                  $result = false;
                                  break 2;
                              }
                          }
                          closedir($handle);
                          return $result;
                      }
                      

                      我使用一个变量来存储结果并将其设置为 true。
                      如果目录为空,则返回的唯一文件是 .和 ..(在 linux 服务器上,如果需要,您可以扩展 mac 的条件),因此条件为真。
                      然后将 result 的值设置为 false 并 break 2 退出 if 和 while 循环,因此下一个执行的语句是 closedir。
                      因此,无论目录是否为空,while 循环在结束之前只有 3 个圆圈。

                      【讨论】:

                        猜你喜欢
                        • 2018-11-20
                        • 2018-12-23
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2018-11-14
                        相关资源
                        最近更新 更多