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


82

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

<?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 2011年

Answers:


134

似乎您需要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;
}

顺便说一句,不要使用单词来代替布尔值。后者的目的是告诉您是否有空。一个

a === b

表达式已经返回EmptyNon Empty使用编程语言,FALSE或者TRUE分别返回了-因此,您可以在IF()没有任何中间值的控件结构中使用该结果


2
我认为我们的代码都是错误的,因为我从该文件夹中删除了所有文件,但仍然说该文件夹不为空...有没有办法检查Linux中的thumbs.db等隐藏文件?
TheBlackBenzKid 2011年

我认为FTP文件夹是..和。在文件中为空。如何检查和删除..和thumbs.db等?
TheBlackBenzKid 2011年

glob不支持linux隐藏文件。如果您想要他们,则必须像删除的答案中那样寻求openir解决方案
您的常识

看来您需要scandir而不是glob。
常识

2
创建测试环境。在脚本所在的同一文件夹中创建空目录。做$dir = 'testfolder';手工。然后运行此代码。调试正在打印出尽可能多的信息,以查看出了什么问题。$dir = 'testfolder';var_dump(scan_dir($dir));会告诉您该目录中的内容
您的常识

69

我认为使用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


7
嗯...为此感到刺痛。
Matt Fletcher 2014年

3
您应该考虑如果$dir不存在则将引发异常。
abdulmanov.ilmir

10

我找到了快速解决方案

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

我在php 5.2中使用的解决方案非常简单。
卢卡斯·摩根

注意,glob看不到隐藏文件。包含“ .htaccess”的目录将使用以下代码视为空
rosell.dk 19/09/16

7

使用

if ($q == "Empty")

代替

if ($q="Empty")

5

对于使用一个面向对象的方法RecursiveDirectoryIterator标准PHP库(SPL)

<?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充分覆盖该部分的。


4

试试这个:

<?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 2011年

当然可以,这只是我的公民职责;-)欢迎使用StackOverflow!
Piotr Nowicki

4

可能由于if语句中的赋值运算符。

更改:

if ($q="Empty")

至:

if ($q=="Empty")

4

这是一个很旧的线程,但我想我要给我十美分。其他解决方案对我不起作用。

这是我的解决方案:

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

简短而甜美。奇迹般有效。


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案件没有得到解决;-)
击败克里斯汀·克里斯滕

@BeatChristen Thx的提示!固定它。
安德烈·菲德勒

我不明白的是为什么您说与“”相比使用严格的比较更好。和“ ..”。readdir()函数将始终返回字符串(或false),所以我看不到重点。我还要补充一点,在自己清理之后确实是个好主意,有人会认为,在返回之后,当$ handle变量超出范围时,closedir()会自动发生,但我只是编写了一个小测试程序,事实并非如此。这很奇怪,因为其他东西(例如羊群)会自动发生。
soger

@AndréFiedler您是个天才,聪明而负责的人。在所有其他答案中,他们首先计算文件总数,然后检查count>0。但是,即使目录包含一个文件,也不为空。
Ashish Doneriya

4

我用了:

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

3

count在大型数组上使用函数的速度可能较慢。isset更快

这将在PHP> = 5.4.0上正常工作(请参见此处的Changelog )

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常识解决方案最好避免在RAM上加载文件列表

也感谢并投票支持@soger,以提高使用SCANDIR_SORT_NONE选项的答案。


3
只要我们担心性能,您可能还需要添加SCANDIR_SORT_NONE参数。
soger

2

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

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

0

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

0

最近,我遇到了类似的问题,尽管最高的答案对我而言并不真正有效,因此,我不得不想出类似的解决方案。同样,这可能也不是解决问题的最有效方法,

我创建了一个像这样的函数

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

0

您可以使用此:

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

0

第一个问题是目录何时为空?在目录中有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);
}

0

@您的常识,@ 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),因此条件为true。
然后将result的值设置为false,并让break 2退出if和while循环,以便执行下一条语句。
因此,无论目录是否为空,while循环在结束之前只有3个圈。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.