如何使用PHP检查一个目录是否为空?

96
我正在使用以下脚本来读取一个目录。如果该目录中没有文件,它应该显示为空。问题是,即使目录中有文件,它仍然会不停地显示目录为空,反之亦然。
```html

我正在使用以下脚本来读取一个目录。如果该目录中没有文件,它应该显示为空。问题是,即使目录中有文件,它仍然会不停地显示目录为空,反之亦然。

```
<?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";
?>

8
你的if语句中只是一个打字错误,需要使用==(比较)代替单个=(赋值)。 - Bas Slagter
19个回答

152

看起来你需要使用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) {
  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;
}

顺便提一下,不要使用“单词”来替代“布尔”值。后者的目的就是告诉你某个东西是否为空。
a === b

在编程语言中,表达式已经返回非空,分别对应falsetrue。因此,您可以在控制结构(例如IF())中直接使用结果,而无需任何中间值。


3
我认为我们的代码都有问题,因为我已经从文件夹中删除了所有文件,但它仍然显示文件夹不为空......在Linux中是否有一种检查隐藏文件(如thumbs.db)的方法? - TheBlackBenzKid
我认为FTP文件夹是说..,而且文件中为空。我该如何检查并删除..和thumbs.db等文件? - TheBlackBenzKid
代码无法工作。没有一个能够工作。如果我有文件在里面,它会说“文件夹不为空”,如果我删除了文件...它还是会说“文件夹不为空”...无论如何,它都无法检测到。 - TheBlackBenzKid
当我删除GET时,没有出现错误。页面是白色 - 空白的。 - TheBlackBenzKid
2
创建测试环境。在脚本所在的同一文件夹中创建一个空目录。手动设置 $dir = 'testfolder';,然后运行此代码。调试将尽可能打印出更多信息以查看出现了什么问题。$dir = 'testfolder';var_dump(scan_dir($dir)); 将告诉您此目录中有什么。 - Your Common Sense
显示剩余9条评论

84

我认为使用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。(详见文档这里。)
如 abdulmanov.ilmir 所指出的,使用 FileSystemIterator 前最好先检查目录是否存在,否则会抛出 UnexpectedValueException 异常。

9
嗯...为此我感到下体有刺痛。 - Matt Fletcher
3
请注意,如果$dir不存在,则会抛出异常。 - abdulmanov.ilmir
简短而精炼。 - marlar
简洁明了。 - marlar

12

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

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

我在php 5.2中使用的解决方案适用于简单情况。 - Lucas
2
请注意,glob函数无法识别隐藏文件。如果一个目录包含“.htaccess”文件,则使用此代码将被视为空目录。 - rosell.dk

7

使用标准PHP库(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 ($q == "Empty")

替代

if ($q="Empty")

为什么给我点踩?有什么原因吗? - Toto

6

这是一个非常老的帖子,但我想说一下我的看法。其他的解决方案对我没有用。

以下是我的解决方案:

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

短小精悍,效果神奇。

5

试试这个:

<?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的第一篇帖子。 - Drmzindec
当然,伙计,这只是我的公民责任;-) 欢迎来到StackOverflow! - Piotr Nowicki

5
我使用了:
if(is_readable($dir)&&count(scandir($dir))==2) ... //then the dir is empty

4

@ 你的常识

我认为你的高性能示例可以更加高效地使用严格比较:

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

1
关于清理的好点子:return false 的情况没有处理它;-) - Beat Christen
@BeatChristen 谢谢提示!已修复。 - André Fiedler
我不明白的是,为什么你说在比较"."和".."时使用严格比较更好。readdir()函数总是会返回一个字符串(或false),所以我不明白这一点。我还想补充一点,自己清理代码确实总是一个好习惯,人们可能认为当$handle变量超出作用域时,closedir()会自动发生,但我刚写了一个小测试程序,它并没有发生。这很奇怪,因为其他东西,比如flock会自动发生。 - soger
@AndréFiedler 您是一个天才,聪明且负责任的人。在所有其他答案中,它们首先计算文件总数,然后检查计数是否大于0。但是,如果目录包含至少一个文件,则不为空。 - Ashish Doneriya

4
可能是因为在 if 语句中使用了赋值运算符。
修改为:
if ($q="Empty")

致:

if ($q=="Empty")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接