Bir dizinin boş olup olmadığını kontrol etmek için PHP'yi nasıl kullanabilirim?


84

Bir dizini okumak için aşağıdaki komut dosyasını kullanıyorum. Dizinde dosya yoksa boş yazmalıdır. Sorun şu ki, içinde dosyalar VAR olmasına rağmen dizinin boş olduğunu söylemeye devam ediyor ve bunun tersi de geçerli.

<?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
Bu sadece if ifadenizde bir yazım hatası. Tekli = (atama) yerine == (karşılaştır) kullanın.
Bas Slagter

Yanıtlar:


134

scandirGlob unix gizli dosyalarını göremediği için glob yerine ihtiyacınız var gibi görünüyor .

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

Dizinin boş olup olmadığını anlamak için tüm dosyaları okumak gereksiz olduğundan, bu kodun verimliliğin zirvesi olmadığını unutmayın. Yani, daha iyi versiyon

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

Bu arada, boole değerlerini değiştirmek için kelimeler kullanmayın . İkincisinin asıl amacı size bir şeyin boş olup olmadığını söylemektir. Bir

a === b

ifade halihazırda Emptyveya Non Emptyprogramlama dili açısından FALSEveya TRUEsırasıyla döner - bu nedenle, sonucu IF()herhangi bir ara değer olmadan kontrol yapılarında kullanabilirsiniz


2
Sanırım her iki kodumuz da yanlış çünkü klasördeki tüm dosyaları kaldırdım ve hala klasörün boş olmadığını söylüyor ... Linux'ta thumbs.db vb. Gibi gizli dosyaları kontrol etmenin bir yolu var mı?
TheBlackBenzKid

Sanırım FTP klasörü diyor ki .. ve. dosyadaki boş. .. ve thumbs.db'nin vb. Olup olmadığını nasıl kontrol edebilirim ve kaldırabilirim?
TheBlackBenzKid

glob, linux gizli dosyalarını desteklemez. Onları istiyorsanız, silinmiş cevapta olduğu gibi openir çözümüne gitmelisiniz
Ortak

Glob yerine skandire ihtiyacın var gibi görünüyor.
Sizin Common Sense

2
Test ortamı oluşturun. betiğin bulunduğu klasörde boş bir dizin oluşturun. yapmak $dir = 'testfolder';elle. daha sonra bu kodu çalıştırın. hata ayıklama, neyin yanlış gittiğini görmek için olabildiğince fazla bilgi yazdırmaktır. $dir = 'testfolder';var_dump(scan_dir($dir));Bu dizinde ne söyleyecektir
Sizin Common Sense

70

FilesystemIterator'ı kullanmanın en hızlı ve en kolay yol olduğunu düşünüyorum :

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

Veya örneklemede sınıf üyesi erişimini kullanarak:

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

Bu işe FilesystemIteratoryarar çünkü yeni bir başlangıçta klasördeki ilk dosyaya işaret eder - klasörde dosya yoksa valid()geri döner false. ( buradaki belgelere bakın .)

Abdulmanov.ilmir tarafından belirtildiği gibi, isteğe bağlı olarak kullanmadan önce dizinin var olup olmadığını kontrol edin, FileSystemIteratoraksi takdirde bir UnexpectedValueException.


8
Mmm ... bunun için belimde karıncalanma.
Matt Fletcher

3
Eğer yoksa $dir, o zaman bir istisna atılacağını düşünmelisiniz .
abdulmanov.ilmir

10

Hızlı bir çözüm buldum

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

Basit durum için php 5.2'de kullandığım çözüm.
Lucas Morgan

1
Glob'un gizli dosyaları görmediğine dikkat edin. Örneğin ".htaccess" içeren bir dizin bu kodla boş kabul edilecektir
rosell.dk

7

kullanım

if ($q == "Empty")

onun yerine

if ($q="Empty")

5

Kullanarak bir nesne yönelimli yaklaşım için RecursiveDirectoryIteratorgelen Standart PHP Kütüphanesi (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;
    }
}

İhtiyaç duyduğunuz her an bir örneğinizi oluşturmanıza FileHelpergerek yok, bu statik yönteme ihtiyacınız olan her yerde şu şekilde erişebilirsiniz:

FileHelper::isEmpty($dir);

FileHelperSınıf, vb kopyalama silme, yeniden adlandırılması için diğer yararlı yöntemler ile uzatılabilir

Yöntemin içindeki dizinin geçerliliğini kontrol etmeye gerek yoktur, çünkü eğer geçersizse, will'in kurucusu o bölümü yeterince kapsayan RecursiveDirectoryIteratorbir şeyi atar UnexpectedValueException.


4

Bunu dene:

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

?>

Teşekkürler! Hızlı bir şekilde yazdım ve buradaki ilk yazım @Piotr Nowicki
Drmzindec

Tabii dostum, bu sadece benim vatandaşlık görevim ;-) StackOverflow'a hoş geldiniz!
Piotr Nowicki

4

Muhtemelen ifadedeki atama operatörü yüzünden if.

Değişiklik:

if ($q="Empty")

Kime:

if ($q=="Empty")

4

Bu çok eski bir konu, ama on sentimi vermeyi düşündüm. Diğer çözümler benim için işe yaramadı.

İşte benim çözümüm:

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

Kısa ve güzel. Tıkır tıkır çalışıyor.


4

@ Sağduyunuz

Performans örneğinizin katı karşılaştırma kullanıldığında daha performanslı olabileceğini düşünüyorum:

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
Temizlemeyle ilgili iyi bir nokta: return falseDava ilgilenmiyor ;-)
Christen'i

İpucu için @BeatChristen Thx! Onu düzeltti.
André Fiedler

Anlamadığım şey, neden "" ile karşılaştırırken katı bir karşılaştırma kullanmanın daha iyi olduğunu söylediğiniz. ve "..". Readdir () işlevi her zaman bir dizge (veya yanlış) döndürür, bu yüzden noktayı görmüyorum. Kendinizden sonra temizlemenin gerçekten her zaman iyi bir fikir olduğunu da eklemek isterim, geri döndükten sonra $ handle değişkeni kapsam dışına çıktığında, closedir () otomatik olarak gerçekleşir, ancak ben sadece küçük bir test programı yazdım ve öyle değil. Bu garip çünkü sürü gibi diğer şeyler otomatik olarak oluyor.
2018

@ AndréFiedler Sen dahisin, zeki ve sorumlu birisin. Diğer tüm cevaplarda, önce toplam dosya sayısını hesaplarlar ve ardından sayının> 0 olup olmadığını kontrol ederler. Ancak bir dizin tek bir dosya içeriyorsa, boş değildir.
Ashish Doneriya

4

Kullandım:

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

3

countBüyük dizide işlev kullanımı yavaş olabilir.issethiç olmadığı kadar hızlı

Bu, PHP> = 5.4.0 üzerinde düzgün çalışacaktır (Değişiklik günlüğüne buradan bakın )

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
}

Aksi takdirde, @ Common Sense çözümünüzü kullanmak, RAM'de dosya listesi yüklemekten kaçınmak için daha iyidir

Teşekkürler ve SCANDIR_SORT_NONEseçeneği kullanarak bu yanıtı iyileştirmek için @soger'a da oy verin .


3
Performans konusunda endişelendiğimiz sürece, SCANDIR_SORT_NONE parametresini de eklemek isteyebilirsiniz.
soger

2

Kodunuzu şu şekilde düzeltin:

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

Bu yöntemi Wordpress CSV 2 POST eklentimde kullanıyorum.

    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
}

Belirli bir uzantı ile çalışır, ancak "yeni RegexIterator (" satırını kaldırarak ihtiyaçlarınıza uyacak şekilde kolayca değiştirilebilir. $ All_files'ı sayın.

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

        return count( $all_files );
    }

0

Son zamanlarda benzer bir sorun yaşadım, ancak en yüksek oyu alan cevap benim için pek işe yaramadı, bu yüzden benzer bir çözüm bulmak zorunda kaldım. ve yine bu, sorunu çözmenin en verimli yolu olmayabilir,

Böyle bir fonksiyon yarattım

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

ve boş dricetory olup olmadığını kontrol etmek için kullandım

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

0

Bunu kullanabilirsiniz:

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

0

İlk soru, bir dizinin ne zaman boş olduğudur? Bir dizinde '.' Adında 2 dosya vardır. ve '..'.
Bunun yanında bir Mac'te '.DS_Store' dosyası olabilir. Bu dosya, dizine bir tür içerik eklendiğinde oluşturulur. Bu 3 dosya dizindeyse, dizinin boş olduğunu söyleyebilirsiniz. Bu nedenle, bir dizinin boş olup olmadığını test etmek için ($ dir'in bir dizin olup olmadığını test etmeden):

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

0

@ Sağduyunuz, @ Enyby

Kodunuzda bazı iyileştirmeler:

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

Sonucu depolamak için bir değişken kullanıyorum ve bunu true olarak ayarlıyorum.
Dizin boşsa, döndürülen dosyalar yalnızca. ve .. (bir linux sunucusunda, gerekirse mac için koşulu genişletebilirsiniz) ve bu nedenle koşul doğrudur.
Ardından sonucun değeri false olarak ayarlanır ve break 2 if ve while döngüsünden çıkar, böylece çalıştırılan sonraki ifade closedir.
Bu nedenle while döngüsü, dizinin boş olup olmadığına bakılmaksızın bitmeden önce yalnızca 3 daireye sahip olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.