¿Cómo puedo usar PHP para verificar si un directorio está vacío?


83

Estoy usando el siguiente script para leer un directorio. Si no hay ningún archivo en el directorio, debería decir vacío. El problema es que sigue diciendo que el directorio está vacío aunque HAY archivos dentro y viceversa.

<?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
Es solo un error tipográfico en su declaración if. Utilice == (comparar) en lugar del único = (asignar).
Bas Slagter

Respuestas:


134

Parece que necesita en scandirlugar de glob, ya que glob no puede ver los archivos ocultos de 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);
}
?>

Tenga en cuenta que este código no es la cima de la eficiencia, ya que no es necesario leer todos los archivos solo para saber si el directorio está vacío. Entonces, la mejor versión sería

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

Por cierto, no use palabras para sustituir valores booleanos . El propósito de este último es decirle si algo está vacío o no. Un

a === b

expresión ya devuelve Emptyo Non Emptyen términos de lenguaje de programación, FALSEo TRUErespectivamente, por lo que puede usar el resultado en estructuras de control como IF()sin valores intermedios


2
Creo que nuestro código es incorrecto porque eliminé todos los archivos de la carpeta y todavía dice que la carpeta no está vacía ... ¿hay alguna manera de buscar archivos ocultos como thumbs.db, etc.en linux?
TheBlackBenzKid

Creo que la carpeta FTP es decir .. y. en el archivo está vacío. ¿Cómo puedo comprobar y eliminar el .. y thumbs.db, etc.?
TheBlackBenzKid

glob no admite archivos ocultos de Linux. si los quiere, debe buscar una solución de openir como en la respuesta eliminada
su sentido común

parece que necesita scandir en lugar de glob.
Tu sentido común

2
Cree un entorno de prueba. cree un directorio vacío en la misma carpeta donde está el script. hacer $dir = 'testfolder';manualmente. luego ejecute este código. depurar es imprimir tanta información como sea posible para ver qué está mal. $dir = 'testfolder';var_dump(scan_dir($dir));le dirá lo que hay en este directorio
su sentido común

69

Creo que usar FilesystemIterator debería ser la forma más rápida y sencilla:

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

O usando el acceso de miembros de la clase en la instanciación:

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

Esto funciona porque un nuevo FilesystemIteratorapuntará inicialmente al primer archivo de la carpeta; si no hay archivos en la carpeta, valid()volverá false. (ver documentación aquí ).

Como lo señaló abdulmanov.ilmir, opcionalmente verifique si el directorio existe antes de usar el FileSystemIteratorporque de lo contrario arrojará un UnexpectedValueException.


7
Mmm ... hormigueo en mis entrañas por este.
Matt Fletcher

3
Debe considerar que si $dirno existe, se lanzará una excepción.
abdulmanov.ilmir

10

Encontré una solución rápida

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

La solución que uso en php 5.2 para un caso simple.
Lucas Morgan

Tenga en cuenta que glob no ve archivos ocultos. Un directorio que contenga, por ejemplo, ".htaccess" se tratará como vacío con este código
rosell.dk

7

utilizar

if ($q == "Empty")

en vez de

if ($q="Empty")

5

Para un enfoque orientado a objetos utilizando el RecursiveDirectoryIteratordel PHP biblioteca estándar (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;
    }
}

No es necesario crear una instancia de su FileHelpercuando lo necesite, puede acceder a este método estático donde lo necesite de esta manera:

FileHelper::isEmpty($dir);

los FileHelper clase se puede ampliar con otros métodos útiles para copiar, borrar, renombrar, etc.

No hay necesidad de verificar la validez del directorio dentro del método porque si no es válido, el constructor RecursiveDirectoryIteratorarrojará un UnexpectedValueExceptionque cubra esa parte suficientemente.


4

Prueba esto:

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

?>

¡Gracias! Lo escribí bastante rápido y es mi primera publicación aquí @Piotr Nowicki
Drmzindec

Seguro amigo, es solo mi deber cívico ;-) ¡Bienvenido a StackOverflow!
Piotr Nowicki

4

Probablemente debido al operador de asignación en if declaración.

Cambio:

if ($q="Empty")

A:

if ($q=="Empty")

4

Este es un hilo muy antiguo, pero pensé en dar mis diez centavos. Las otras soluciones no funcionaron para mí.

Aquí está mi solución:

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

Corto y dulce. Funciona de maravilla.


4

@ Tu sentido común

Creo que su ejemplo de rendimiento podría ser más eficaz utilizando una comparación estricta:

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
Buen punto con respecto a la limpieza: el return falsecaso no se está ocupando de él ;-)
Beat Christen

@BeatChristen Thx por la pista! Arreglado.
André Fiedler

Lo que no entiendo es por qué dice que es mejor utilizar una comparación estricta cuando se compara con "." y "..". La función readdir () siempre devolverá una cadena (o el falso) así que no veo el punto. También me gustaría agregar que limpiar después de ti mismo es siempre una buena idea, uno pensaría que después de regresar cuando la variable $ handle se sale del alcance, closedir () sucedería automáticamente, pero acabo de escribir un pequeño programa de prueba, y no es así. Lo cual es extraño porque otras cosas, como el rebaño, suceden automáticamente.
soger

@ AndréFiedler Eres una persona genial, brillante y responsable. En todas las demás respuestas, primero calculan el número total de archivos y luego verifican si el recuento es> 0. Pero si un directorio contiene incluso un archivo, no está vacío.
Ashish Doneriya

4

Solía:

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

3

El countuso de funciones puede ser lento en una gran variedad.issetes cada vez más rápido

Esto funcionará correctamente en PHP> = 5.4.0 (consulte el registro de cambios aquí )

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
}

De lo contrario, usar @Your Common Sense es mejor para evitar cargar la lista de archivos en la RAM

Gracias y vote a @soger también, para mejorar esta respuesta usando la SCANDIR_SORT_NONEopción.


3
Mientras nos preocupemos por el rendimiento, es posible que también desee agregar el parámetro SCANDIR_SORT_NONE.
soger

2

Solo corrige tu código así:

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

Utilizo este método en mi complemento 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
}

Funciona con una extensión específica, pero se cambia fácilmente para adaptarse a sus necesidades eliminando la línea "new RegexIterator (". Count $ all_files.

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

        return count( $all_files );
    }

0

Recientemente tuve un problema similar, aunque la respuesta más votada no me funcionó, por lo tanto, tuve que encontrar una solución similar. y, de nuevo, esta puede no ser la forma más eficaz de solucionar el problema,

Creé una función así

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

y lo usé para buscar dricetory vacío como tal

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

0

Puedes usar esto:

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

0

La primera pregunta es ¿cuándo está vacío un directorio? En un directorio hay 2 archivos, el '.' y '..'.
Junto a eso en una Mac, tal vez esté el archivo '.DS_Store'. Este archivo se crea cuando se agrega algún tipo de contenido al directorio. Si estos 3 archivos están en el directorio, puede decir que el directorio está vacío. Entonces, para probar si un directorio está vacío (sin probar si $ dir es un directorio):

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

0

@ Tu sentido común, @ Enyby

Alguna mejora de su código:

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

Utilizo una variable para almacenar el resultado y lo configuro en verdadero.
Si el directorio está vacío, los únicos archivos que se devuelven son. y .. (en un servidor Linux, puede extender la condición para mac si es necesario) y, por lo tanto, la condición es verdadera.
Luego, el valor del resultado se establece en falso y el corte 2 sale del bucle if y while para que la siguiente instrucción ejecutada sea cerrada.
Por lo tanto, el ciclo while solo tendrá 3 círculos antes de que termine, independientemente de si el directorio está vacío o no.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.