Làm cách nào tôi có thể sử dụng PHP để kiểm tra xem một thư mục có trống không?


83

Tôi đang sử dụng tập lệnh sau để đọc một thư mục. Nếu không có tệp nào trong thư mục, nó sẽ nói trống. Vấn đề là, nó vẫn tiếp tục thông báo thư mục trống mặc dù có tệp bên trong và ngược lại.

<?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
Đó chỉ là lỗi đánh máy trong câu lệnh if của bạn. Sử dụng == (so sánh) thay vì = (gán) duy nhất.
Bas Slagter,

Câu trả lời:


134

Có vẻ như bạn cần scandirthay vì pc, vì vc không thể thấy các tệp ẩn 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);
}
?>

Lưu ý rằng mã này không phải là đỉnh của hiệu quả, vì không cần thiết phải đọc tất cả các tệp chỉ để biết thư mục có trống hay không. Vì vậy, phiên bản tốt hơn sẽ là

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

Nhân tiện, không sử dụng các từ để thay thế các giá trị boolean . Mục đích của phần sau là để cho bạn biết liệu có gì đó trống rỗng hay không. An

a === b

biểu thức đã trả về Emptyhoặc Non Emptytheo ngôn ngữ lập trình, FALSEhoặc TRUEtương ứng - vì vậy, bạn có thể sử dụng chính kết quả trong các cấu trúc điều khiển như IF()không có bất kỳ giá trị trung gian nào


2
Tôi nghĩ rằng cả hai mã của chúng tôi đều sai vì tôi đã xóa tất cả các tệp khỏi thư mục và nó vẫn thông báo thư mục không trống ... có cách nào để kiểm tra các tệp ẩn như thumbs.db, v.v. trong linux không ??
TheBlackBenzKid

Tôi nghĩ rằng thư mục FTP nói .. và. trong tệp trống. Làm cách nào tôi có thể kiểm tra xem và xóa .. và thumbs.db, v.v. ??
TheBlackBenzKid

cầu không hỗ trợ các tệp ẩn linux. nếu bạn muốn họ bạn phải đi cho giải pháp openir như trong câu trả lời đã xóa
bạn Common Sense

có vẻ như bạn cần scandir thay vì cầu.
Your Common Sense,

2
Tạo môi trường thử nghiệm. tạo thư mục trống trong cùng thư mục chứa script. làm $dir = 'testfolder';thủ công. sau đó chạy mã này. gỡ lỗi đang in ra càng nhiều thông tin càng tốt để xem điều gì đang xảy ra. $dir = 'testfolder';var_dump(scan_dir($dir));sẽ cho bạn biết có gì trong thư mục này
Your Common Sense,

69

Tôi nghĩ rằng việc sử dụng FilesystemIterator sẽ là cách nhanh nhất và dễ dàng nhất:

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

Hoặc sử dụng quyền truy cập của thành viên lớp trên khởi tạo:

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

Điều này hoạt động vì một FilesystemIteratortệp mới ban đầu sẽ trỏ đến tệp đầu tiên trong thư mục - nếu không có tệp nào trong thư mục, tệp valid()sẽ trở lại false. (xem tài liệu tại đây .)

Như đã chỉ ra bởi Abdulmanov.ilmir, hãy tùy ý kiểm tra xem thư mục có tồn tại hay không trước khi sử dụng FileSystemIteratorvì nếu không nó sẽ ném ra UnexpectedValueException.


7
Mmm ... ngứa ran trong thắt lưng của tôi vì cái này.
Matt Fletcher

3
Bạn nên xem xét rằng nếu $dirkhông tồn tại thì một ngoại lệ sẽ được ném ra.
Abdulmanov.ilmir

10

Tôi đã tìm thấy một giải pháp nhanh chóng

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

Giải pháp tôi sử dụng trong php 5.2 cho trường hợp đơn giản.
Lucas Morgan,

Hãy cẩn thận rằng bong bóng không nhìn thấy các tệp ẩn. Một thư mục chứa ie ".htaccess" sẽ được coi như sản phẩm nào với mã này
rosell.dk

7

sử dụng

if ($q == "Empty")

thay vì

if ($q="Empty")

5

Đối với một cách tiếp cận hướng đối tượng bằng cách sử dụng RecursiveDirectoryIteratortừ Thư viện PHP Chuẩn (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;
    }
}

Không cần phải tạo một phiên bản của bạn FileHelperbất cứ khi nào bạn cần, bạn có thể truy cập phương thức tĩnh này bất cứ khi nào bạn cần như sau:

FileHelper::isEmpty($dir);

Các FileHelperlớp có thể được mở rộng với các phương pháp hữu ích khác để sao chép, xóa, đổi tên, vv

Không cần phải kiểm tra tính hợp lệ của thư mục bên trong phương thức bởi vì nếu nó không hợp lệ, phương thức khởi tạo của RecursiveDirectoryIteratorwill ném một thư mục UnexpectedValueExceptionbao phủ đủ phần đó.


4

Thử đi:

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

?>

Cảm ơn! Tôi đã viết nó khá nhanh chóng và sau nó tôi trước đây @Piotr Nowicki
Drmzindec

Chắc chắn bạn đời ơi, đó chỉ là nghĩa vụ công dân của tôi ;-) Chào mừng bạn đến với StackOverflow!
Piotr Nowicki

4

Có thể là do toán tử gán trong ifcâu lệnh.

Thay đổi:

if ($q="Empty")

Đến:

if ($q=="Empty")

4

Đây là một chủ đề rất cũ, nhưng tôi nghĩ rằng tôi sẽ cho mười xu của mình. Các giải pháp khác không hiệu quả với tôi.

Đây là giải pháp của tôi:

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

Ngắn và ngọt. Hoạt động như một sự quyến rũ.


4

@ Ý thức chung của bạn

Tôi nghĩ ví dụ về hiệu suất của bạn có thể hiệu quả hơn bằng cách sử dụng so sánh chặt chẽ:

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
Tốt điểm về dọn dẹp: Các return falsetrường hợp không được chăm sóc nó ;-)
Đánh bại Christen

@BeatChristen Thx cho gợi ý! Đã sửa nó.
André Fiedler

Điều tôi không hiểu là tại sao bạn nói rằng tốt hơn là sử dụng phép so sánh chặt chẽ khi so sánh với "." và "..". Hàm readdir () sẽ luôn trả về một chuỗi (hoặc sai) vì vậy tôi không thấy điểm. Tôi cũng muốn nói thêm rằng việc tự dọn dẹp thực sự luôn là một ý kiến ​​hay, người ta sẽ nghĩ rằng sau khi trả về khi biến $ handle ra khỏi phạm vi, thì closedir () sẽ tự động xảy ra nhưng tôi chỉ viết một chương trình thử nghiệm nhỏ, và nó không. Thật kỳ lạ vì những thứ khác, chẳng hạn như bầy đàn xảy ra tự động.
soger

@ AndréFiedler Bạn là một thiên tài, người tài giỏi và có trách nhiệm. Trong tất cả các câu trả lời khác, trước tiên họ tính tổng số tệp và sau đó kiểm tra xem số lượng có> 0. Nhưng nếu một thư mục chứa thậm chí một tệp, thì nó không trống.
Ashish Doneriya

4

Tôi đã sử dụng:

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

3

countViệc sử dụng hàm có thể chậm trên mảng lớn. issetnhanh hơn bao giờ hết

Điều này sẽ hoạt động bình thường trên PHP> = 5.4.0 (xem Changelog tại đây )

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
}

Nếu không, sử dụng giải pháp @Your Common Sense sẽ tốt hơn để tránh tải danh sách tệp trên RAM

Cảm ơn và cũng bỏ phiếu cho @soger, để cải thiện câu trả lời này bằng cách sử dụng SCANDIR_SORT_NONEtùy chọn.


3
Miễn là chúng tôi lo lắng về hiệu suất, bạn cũng có thể muốn thêm thông số SCANDIR_SORT_NONE.
soger

2

Chỉ cần sửa mã của bạn như sau:

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

Tôi sử dụng phương pháp này trong plugin Wordpress CSV 2 POST của mình.

    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
}

Nó hoạt động theo tiện ích mở rộng cụ thể nhưng có thể dễ dàng thay đổi để phù hợp với nhu cầu của bạn bằng cách xóa dòng "new RegexIterator (". Đếm $ all_files.

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

        return count( $all_files );
    }

0

Tôi đã gặp vấn đề tương tự gần đây, mặc dù câu trả lời được bình chọn cao nhất không thực sự phù hợp với tôi, do đó, tôi phải đưa ra một giải pháp tương tự. và một lần nữa, đây cũng có thể không phải là cách hiệu quả nhất để giải quyết vấn đề,

Tôi đã tạo một chức năng như vậy

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

và sử dụng nó để kiểm tra xem có trống rỗng như vậy không

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

0

Bạn có thể sử dụng cái này:

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

0

Câu hỏi đầu tiên là khi nào thì một thư mục trống? Trong một thư mục có 2 tệp là '.' và '..'.
Bên cạnh đó trên máy Mac có thể có tệp '.DS_Store'. Tệp này được tạo khi một số loại nội dung được thêm vào thư mục. Nếu 3 tệp này nằm trong thư mục, bạn có thể nói rằng thư mục trống. Vì vậy, để kiểm tra xem một thư mục có trống không (mà không cần kiểm tra nếu $ dir là một thư mục):

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

0

@Your Common Sense, @ Enyby

Một số cải tiến mã của bạn:

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

Tôi sử dụng một biến để lưu trữ kết quả và đặt nó thành true.
Nếu thư mục trống, chỉ có các tệp được trả về. và .. (trên máy chủ linux, bạn có thể mở rộng điều kiện cho mac nếu bạn cần) và do đó điều kiện là đúng.
Sau đó, giá trị của kết quả được đặt thành false và break 2 thoát khỏi vòng lặp if và while để câu lệnh tiếp theo được thực thi là đóng.
Do đó vòng lặp while sẽ chỉ có 3 vòng tròn trước khi kết thúc bất kể thư mục có trống hay không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.