PHP를 사용하여 디렉토리가 비어 있는지 어떻게 확인할 수 있습니까?


84

다음 스크립트를 사용하여 디렉토리를 읽고 있습니다. 디렉토리에 파일이 없으면 비어 있어야합니다. 문제는 내부에 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

답변:


134

scandirglob은 unix 숨겨진 파일을 볼 수 없기 때문에 glob 대신 필요한 것 같습니다 .

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

표현식은 이미 Empty또는 Non Empty프로그래밍 언어 측면에서 FALSE또는 TRUE각각 반환 하므로 IF()중간 값없이 같은 제어 구조에서 바로 결과를 사용할 수 있습니다.


2
나는 폴더에서 모든 파일을 제거했지만 여전히 폴더가 비어 있지 않다고 말하기 때문에 우리 코드가 잘못되었다고 생각합니다 ... 리눅스에서 thumb.db 등과 같은 숨겨진 파일을 확인하는 방법이 있습니까 ??
TheBlackBenzKid 2011 년

FTP 폴더는 .. 및. 파일이 비어 있습니다. .. 및 thumb.db 등을 어떻게 확인하고 제거 할 수 있습니까 ??
TheBlackBenzKid 2011 년

glob은 Linux 숨김 파일을 지원하지 않습니다. 당신이 그들을 원한다면 삭제 된 답변에서와 같이 openir 솔루션을 찾아야합니다
당신의 상식

glob 대신 scandir이 필요한 것 같습니다.
당신의 상식

2
테스트 환경을 만드십시오. 스크립트가있는 동일한 폴더에 빈 디렉터리를 만듭니다. $dir = 'testfolder';수동으로 만드십시오 . 그런 다음이 코드를 실행하십시오. 디버그는 무엇이 잘못되었는지 확인하기 위해 가능한 한 많은 정보를 인쇄하는 것입니다. $dir = 'testfolder';var_dump(scan_dir($dir));이 디렉토리에있는 무엇을 말할 것이다
당신의 상식

70

FilesystemIterator를 사용하는 것이 가장 빠르고 쉬운 방법 이라고 생각합니다 .

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

또는 인스턴스화시 클래스 멤버 액세스 사용 :

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

이것은 new FilesystemIterator가 처음에 폴더의 첫 번째 파일을 가리 키기 때문에 작동 합니다. 폴더에 파일 valid()이 없으면를 반환 false합니다. ( 여기에서 문서를 참조 하십시오 .)

abdulmanov.ilmir가 지적했듯이, 선택적으로를 사용하기 전에 디렉토리가 존재하는지 확인하십시오 . FileSystemIterator그렇지 않으면 UnexpectedValueException.


8
음 .. 이건 내 허리가 따끔 거린다.
Matt Fletcher

3
$dir가 존재하지 않으면 예외가 발생 한다는 점을 고려해야합니다 .
abdulmanov.ilmir

10

빠른 해결책을 찾았습니다

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

간단한 경우에 PHP 5.2에서 사용하는 솔루션입니다.
Lucas Morgan

1
glob은 숨겨진 파일을 볼 수 없습니다. 즉, "htaccess로"를 포함하는 디렉토리는이 코드를 빈으로 처리됩니다
rosell.dk

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

물론 친구, 그것은 내 시민의 의무입니다 ;-) StackOverflow에 오신 것을 환영합니다!
Piotr Nowicki 2011

4

아마도 if문장 의 할당 연산자 때문일 것입니다 .

변화:

if ($q="Empty")

에:

if ($q=="Empty")

4

이것은 매우 오래된 실이지만 10 센트를 줄 것이라고 생각했습니다. 다른 솔루션은 저에게 효과적이지 않았습니다.

내 해결책은 다음과 같습니다.

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! 고쳤다.
앙드레 Fiedler는

내가 이해하지 못하는 것은 "."와 비교할 때 엄격한 비교를 사용하는 것이 더 낫다고 말하는 이유입니다. 그리고 "..". readdir () 함수는 항상 문자열 (또는 false)을 반환하므로 요점이 보이지 않습니다. 나는 또한 자신을 정리하는 것이 항상 좋은 생각이라는 것을 덧붙이고 싶습니다. 그리고 그렇지 않습니다. 무리와 같은 다른 일이 자동으로 발생하기 때문에 이상합니다.
soger

@ AndréFiedler 당신은 천재적이고 똑똑하고 책임감있는 사람입니다. 다른 모든 답변에서는 먼저 총 파일 수를 계산 한 다음 count> 0인지 확인합니다. 그러나 디렉토리에 파일이 하나라도 포함되어 있으면 비어 있지 않습니다.
Ashish Doneriya 19.04.09

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 Common Sense 솔루션을 사용하여 RAM에 파일 목록로드를 피하는 것이 좋습니다.

SCANDIR_SORT_NONE옵션을 사용하여이 답변을 개선하기 위해 @soger에게도 감사하고 투표하십시오 .


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로 설정합니다.
디렉토리가 비어 있으면 반환되는 유일한 파일은. 그리고 .. (리눅스 서버에서는 필요한 경우 mac에 대한 조건을 확장 할 수 있습니다) 따라서 조건이 참입니다.
그런 다음 결과 값은 false로 설정되고 break 2는 if 및 while 루프를 종료하므로 실행되는 다음 문이 closedir입니다.
따라서 while 루프에는 디렉토리가 비어 있는지 여부에 관계없이 끝나기 전에 3 개의 원만 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.