scandir()
Aprende a usar la función scandir() de PHP para leer el contenido de un directorio, ordenarlo, filtrarlo y manejar errores de forma segura.
Introducción
El manejo de directorios es una parte esencial de la programación en PHP — casi todo script de copia de seguridad, cargador de archivos o procesador de recursos necesita listar lo que hay dentro de una carpeta. Este artículo profundiza en la función scandir() de PHP, que lee el contenido de un directorio en una sola llamada. Aprenderás qué devuelve, cómo ordenar y filtrar el resultado, en qué se diferencia de glob() y cómo manejar errores de forma segura.
¿Qué es scandir?
scandir() lee un directorio y devuelve los nombres de todas las entradas que contiene — archivos y subdirectorios — como un array plano de strings. El array siempre incluye las dos entradas especiales . (el directorio actual) y .. (el directorio padre), por lo que casi siempre se filtran antes de usar el resultado.
Si el directorio no puede leerse, scandir() devuelve false y emite una advertencia. La función está disponible desde PHP 4.3.0 y funciona tanto en sistemas Unix como en Windows.
Sintaxis
scandir(string $directory, int $sorting_order = SCANDIR_SORT_ASCENDING, ?resource $context = null): array|false| Parámetro | Descripción |
|---|---|
$directory | Ruta al directorio que deseas leer. Puede ser absoluta o relativa al directorio de trabajo del script. |
$sorting_order | Cómo se ordena el resultado: SCANDIR_SORT_ASCENDING (predeterminado, A→Z), SCANDIR_SORT_DESCENDING (Z→A), o SCANDIR_SORT_NONE (orden del sistema de archivos — el más rápido, sin ordenación). |
$context | Un recurso de contexto de flujo opcional (raramente necesario; se usa para envoltorios de flujo personalizados). |
La función devuelve un array de nombres de archivo en caso de éxito o false en caso de error.
Los nombres se devuelven sin la ruta del directorio. Para obtener una ruta utilizable, antepón el directorio tú mismo:
$directory . '/' . $entry.
¿Cómo funciona scandir?
En su forma más simple, solo se pasa la ruta del directorio. El contenido se devuelve ordenado alfabéticamente (ascendente) porque ese es el $sorting_order predeterminado. El siguiente ejemplo filtra . y .. con array_diff() para que solo queden entradas reales:
Ejemplo de la función scandir() en PHP
<?php
$dir = "/path/to/directory";
$files = scandir($dir);
// Filter out the current and parent directory entries
$filtered = array_diff($files, ['.', '..']);
foreach ($filtered as $file) {
echo $file . "<br>";
}Este código muestra una lista de archivos y subdirectorios en el directorio especificado, excluyendo . y ...
Ordenar el contenido del directorio
Pasa un segundo argumento para controlar el orden del resultado. Las tres opciones son:
SCANDIR_SORT_ASCENDING— alfabético A→Z (el predeterminado).SCANDIR_SORT_DESCENDING— alfabético Z→A.SCANDIR_SORT_NONE— sin ordenación; las entradas se devuelven en el orden que proporciona el sistema de archivos. Es la opción más rápida y vale la pena usarla cuando vas a ordenar la lista tú mismo de todas formas, o cuando el orden no importa.
Por ejemplo, dado un directorio que contiene archive.txt, data.csv, report.txt, notes.md, image.png y un subdirectorio backups:
Cómo ordenar la salida de scandir() en orden descendente
<?php
$dir = "/path/to/directory";
$files = scandir($dir, SCANDIR_SORT_DESCENDING);
print_r($files);
// Array
// (
// [0] => report.txt
// [1] => notes.md
// [2] => image.png
// [3] => data.csv
// [4] => backups
// [5] => ..
// [6] => .
// )Los mismos datos con SCANDIR_SORT_NONE se devuelven sin ordenar (el orden exacto depende del sistema de archivos), lo que evita la pequeña sobrecarga de la ordenación.
Listar solo archivos (o solo directorios)
scandir() devuelve archivos y carpetas mezclados. Para conservar solo archivos, prueba cada entrada con is_file(); para conservar solo directorios, usa is_dir(). Recuerda construir la ruta completa primero:
<?php
$dir = "/path/to/directory";
$entries = array_diff(scandir($dir), ['.', '..']);
$filesOnly = array_filter($entries, fn($entry) => is_file($dir . '/' . $entry));
print_r(array_values($filesOnly));
// Array
// (
// [0] => archive.txt
// [1] => data.csv
// [2] => image.png
// [3] => notes.md
// [4] => report.txt
// )Filtrar por extensión de archivo
Una tarea habitual es obtener solo los archivos de un tipo determinado. Combina scandir() con pathinfo() para leer la extensión de cada entrada:
<?php
$dir = "/path/to/directory";
$entries = array_diff(scandir($dir), ['.', '..']);
$textFiles = array_filter(
$entries,
fn($entry) => pathinfo($entry, PATHINFO_EXTENSION) === 'txt'
);
print_r(array_values($textFiles));
// Array
// (
// [0] => archive.txt
// [1] => report.txt
// )Si solo necesitas buscar archivos por un patrón, glob() puede hacerlo en un paso — por ejemplo glob("$dir/*.txt") — y devuelve rutas completas. Usa glob() para coincidencia de patrones y scandir() cuando quieras todas las entradas y control total sobre el filtrado.
Manejo de errores
La función scandir puede fallar si la ruta del directorio especificada no es válida o si el directorio no tiene los permisos adecuados. En caso de error, devuelve false y genera una advertencia. No lanza excepciones, por lo que debes comprobar el valor de retorno directamente. Aquí tienes un ejemplo:
Ejemplo de la función scandir() en PHP con manejo de errores
<?php
$dir = "/path/to/directory";
$files = scandir($dir);
if ($files === false) {
echo "Error: Could not read the directory.";
} else {
foreach ($files as $file) {
echo $file . "<br>";
}
}Este código comprueba el valor de retorno de scandir() y muestra un mensaje de error si el directorio no puede leerse. Como scandir() genera una advertencia (no una excepción) cuando falla, la comprobación estricta === false es lo que realmente protege tu código — y silenciar la advertencia con @scandir() no es recomendable, ya que pierdes el mensaje de diagnóstico.
Para evitar la advertencia por completo, confirma que la ruta es un directorio legible antes de llamar a scandir():
<?php
$dir = "/path/to/directory";
if (is_dir($dir)) {
$files = scandir($dir);
foreach (array_diff($files, ['.', '..']) as $file) {
echo $file . "<br>";
}
} else {
echo "Error: '$dir' is not a valid directory.";
}scandir() frente a otras funciones de directorio
| Función | Devuelve | Ideal para |
|---|---|---|
scandir() | Un array con todos los nombres de entradas a la vez | Obtener el listado completo en una línea y luego filtrar/ordenar |
glob() | Rutas completas que coinciden con un patrón | Coincidencia de patrones como *.jpg |
opendir() + readdir() | Un manejador de directorio que se lee entrada por entrada | Directorios muy grandes donde no se quiere cargar toda la lista en memoria |
Para una visión general del conjunto de herramientas disponibles, consulta Trabajar con directorios en PHP.
Conclusión
La función scandir() es una forma cómoda de leer el contenido de un directorio en PHP con una sola llamada. Has visto cómo listar entradas, ordenarlas con las tres constantes SCANDIR_SORT_*, conservar solo archivos o solo directorios, filtrar por extensión y manejar errores de forma segura. Usa scandir() cuando quieras el listado completo y control total; usa glob() cuando una simple coincidencia de patrón sea suficiente.