¿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";
?>
TheBlackBenzKid
fuente
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

Tu sentido común
fuente
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.

gripe
fuente
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';
?>
Franco
fuente
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")
Toto
fuente
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.

Marchitar
fuente
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";
} 

?>
Drmzindec
fuente
¡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")
Robik
fuente
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.

narfie
fuente
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;
}
André Fiedler
fuente
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
Luca C.
fuente
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.

Oscar Zarrus
fuente
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";
    }
?>
Alessandro.Vegna
fuente
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 );
    }
Ryan Bayne
fuente
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);
        }
user28864
fuente
0

Puedes usar esto:

function isEmptyDir($dir)
{
    return (($files = @scandir($dir)) && count($files) <= 2);
}
karrtojal
fuente
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);
}
Daño
fuente
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.

Alexander Behling
fuente