Directorios en PHP: scandir(), glob(), mkdir() y recorrer árboles de ficheros

PHP tiene cuatro herramientas principales para trabajar con directorios: scandir() para listar el contenido, glob() para buscar con patrones, mkdir() para crear directorios de forma recursiva y RecursiveDirectoryIterator para recorrer árboles completos de ficheros.

scandir(): listar el contenido de un directorio

<?php
// Lista todos los entries, incluyendo '.' y '..'
$todo = scandir('/var/www/app/uploads');

// Filtrar '.' y '..'
$ficheros = array_diff(scandir('/var/www/app/uploads'), ['.', '..']);

// Orden descendente (segundo parámetro)
$descendente = scandir('/var/www/app/uploads', SCANDIR_SORT_DESCENDING);

// Uso habitual: listar solo ficheros (no subdirectorios)
$dir = '/var/www/app/uploads';
$soloFicheros = array_filter(
    array_diff(scandir($dir), ['.', '..']),
    fn($entry) => is_file("$dir/$entry")
);
?>

glob(): listar ficheros con patrones

glob() acepta los mismos comodines que la shell: * para cualquier cadena, ? para un solo carácter, [abc] para un conjunto y {a,b} para alternativas:

<?php
// Todos los PHP del directorio actual
$phps = glob('*.php');

// Todos los JPG y PNG de uploads
$imagenes = glob('/var/www/app/uploads/*.{jpg,jpeg,png,gif,webp}', GLOB_BRACE);

// Todos los logs de julio de 2026
$logs = glob('/var/log/app/2026-07-*.log');

// Todos los directorios dentro de un path
$subdirs = glob('/var/www/app/*', GLOB_ONLYDIR);

foreach ($imagenes as $ruta) {
    echo basename($ruta) . ' - ' . filesize($ruta) . " bytesn";
}
?>

mkdir(): crear directorios

<?php
// Crear un directorio simple
mkdir('/tmp/nuevo-dir');

// Crear con permisos específicos
mkdir('/var/www/app/cache', 0755);

// Crear toda la estructura recursivamente (tercer parámetro true)
$ruta = '/var/www/app/uploads/2026/07/26';
if (!is_dir($ruta)) {
    mkdir($ruta, 0755, true); // crea 2026/, 2026/07/, 2026/07/26/
}
?>

Organizar subidas por fecha

<?php
function subirFichero(array $fichero): string
{
    $base     = '/var/www/app/uploads';
    $subdir   = date('Y/m/d'); // ej. 2026/07/26
    $directorio = "$base/$subdir";

    if (!is_dir($directorio)) {
        mkdir($directorio, 0755, true);
    }

    $nombre  = uniqid('img_', true) . '.' . pathinfo($fichero['name'], PATHINFO_EXTENSION);
    $destino = "$directorio/$nombre";

    if (!move_uploaded_file($fichero['tmp_name'], $destino)) {
        throw new RuntimeException("No se pudo mover el fichero a $destino");
    }

    // Ruta relativa para guardar en BD
    return "uploads/$subdir/$nombre";
}
?>

RecursiveDirectoryIterator: recorrer árboles

Para recorrer un directorio con todos sus subdirectorios, RecursiveDirectoryIterator combinado con RecursiveIteratorIterator es la herramienta más potente:

<?php
$directorio = '/var/www/app/src';
$iterador   = new RecursiveDirectoryIterator(
    $directorio,
    RecursiveDirectoryIterator::SKIP_DOTS
);
$aplanado   = new RecursiveIteratorIterator($iterador);

foreach ($aplanado as $fichero) {
    if ($fichero->isFile()) {
        echo $fichero->getRealPath() . "n";
    }
}
?>

Buscar ficheros por extensión en todo el árbol

<?php
function buscarPorExtension(string $directorio, string $extension): array
{
    $resultado = [];
    $iterador  = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($directorio, FilesystemIterator::SKIP_DOTS)
    );

    foreach ($iterador as $fichero) {
        if (strtolower($fichero->getExtension()) === strtolower($extension)) {
            $resultado[] = $fichero->getRealPath();
        }
    }

    return $resultado;
}

// Buscar todos los ficheros .log en /var/log
$logs = buscarPorExtension('/var/log', 'log');
echo count($logs) . " ficheros .log encontradosn";

// Buscar todos los .php en el proyecto
$phps = buscarPorExtension('/var/www/app/src', 'php');
echo count($phps) . " ficheros PHP encontradosn";
?>

Calcular el tamaño de un directorio

<?php
function tamanoDirectorio(string $directorio): int
{
    $total    = 0;
    $iterador = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($directorio, FilesystemIterator::SKIP_DOTS)
    );
    foreach ($iterador as $fichero) {
        $total += $fichero->getSize();
    }
    return $total;
}

$bytes = tamanoDirectorio('/var/www/app/uploads');
echo number_format($bytes / 1024 / 1024, 2) . ' MB';
?>

La documentación de RecursiveDirectoryIterator cubre las opciones de FilesystemIterator y los flags para controlar qué incluir en la iteración.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP