Leer árbol de directorios recursivo con PHP

En este artículo vamos a ver cómo leer un árbol de directorios recursivo con PHP, mostrarlo en forma de lista HTML y devolver el resultado en un Array con las rutas.

Leer árbol de directorios recursivo con PHP

Leer los archivos de un directorio con PHP es muy fácil y se encuentra explicado en un artículo anterior: leer archivos de un directorio con php. Simplemente utilizamos una función para leer todos los archivos que se encuentren en el directorio.

Pero si queremos leer un árbol de directorios nos encontramos con un problema: dentro de cada directorio, a parte de archivos, pueden haber otros directorios con más archivos, hasta un número indeterminado de profundidad.

La incertidumbre de saber a cuántos niveles de profundidad debemos ir hace difícil programar un algoritmo capaz de leer archivos, junto con otro que cambie de directorio hasta el nivel … infinito?

Para solucionar este problema tanto PHP como otros lenguajes de programación permiten crear funciones recursivas. Si no sabes lo que es una función recursiva, se trata de una función que se llama a sí misma un número indeterminado de veces. Puedes ver su definición en la Wikipedia: Recursividad.

Esto nos permite crear una función que reciba como parámetro un directorio y simplemente se encargue de leer los archivos de ese directorio. Si uno de los archivos se trata de un directorio, volvemos a llamar a la función con este nuevo directorio.

Así hasta el número de directorios que se vallan encontrando. Vamos a ver la función dentro de una página PHP que nos devolverá el árbol de directorios recursivo que le indiquemos.

Función recursiva con PHP

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <h2>Listado de directorios y archivos</h2>

<?php
// Función recursiva para leer archivos y directorios
function obtener_estructura_directorios($ruta) {
  // Array para guardar el directorio y los archivos
  $mi_estructura = [];
  // Se comprueba que realmente sea la ruta de un directorio
  if (is_dir($ruta)) {
    // Abre un gestor de directorios para la ruta indicada
    $gestor = opendir($ruta);
    echo "<ul>";
    // Recorre todos los elementos del directorio
    while (($archivo = readdir($gestor)) !== false)  {
      $ruta_completa = $ruta . "/" . $archivo;
      // Mostramos todos los archivos y directorios excepto "." y ".."
      if ($archivo != "." && $archivo != "..") {
        echo "<li>" . $archivo . "</li>";
        // Si es un directorio se recorre recursivamente
        if (is_dir($ruta_completa)) {
          // Añadimos el array (recursivo) del siguiente directorio 
          $mi_estructura = array_merge($mi_estructura, obtener_estructura_directorios($ruta_completa));
          // Si es un archivo añadimos ruta/archivo al Array
        }else {
          $mi_estructura[] = ['ruta' => $ruta.'/', 'archivo' => $archivo];
        }
      }
    }
    // Cierra el gestor de directorios
    closedir($gestor);
    echo "</ul>";
  } else echo "$ruta No es una ruta de directorio valida<br/>";
  // Devolvemos el array del directorio actual  
  return $mi_estructura;
}

// Activamos la función recursiva
$resultado = obtener_estructura_directorios('../');

// Mostramos contenido del Array
echo '<h2>Contenido del Array</h2>';
for($i=0; $i<count($resultado); $i++) {
  echo $resultado[$i]['ruta'].$resultado[$i]['archivo'].'<br>';
}

// Mostramos Array con var_dump()
echo '<h2>var_dump del Array</h2>';
var_dump($resultado);
?>

</body>
</html>

Vamos a explicar por trozos lo que hace esta página PHP empezando por el funcionamiento de la función:

  • La función recibe el parámetro $ruta con el directorio que queremos leer sus archivos
  • La función define la variable local $mi_estructura como un Array vacío donde guardaremos de forma asociativa tanto la ruta como los archivo encontrados
  • Comprobamos que $ruta sea un directorio con el condicional is_dir(), si no lo fuera, devuelve un mensaje de $ruta inválida
  • Abrimos el directorio y abrimos una lista <ul>
    • Con el directorio abierto obtenemos sus archivos en un bucle while
      • Para cada archivo encontrado guardamos su $ruta_completa
      • Descriminamos los archivos del sistema windows «.» y «..»
      • Mostramos cada archivo encontrado en una lista <li>
      • Preguntamos si el archivo es un directorio
        • En caso afirmativo llamamos a la función de forma recursiva con el nuevo directorio a leer. Su resultado lo añadiremos a $mi_estructura del directorio actual
        • En caso negativo añadimos $ruta y $archivo de forma asociativa a $mi_estructura actual
  • Cerramos el listado de archivos </ul>
  • Devolvemos el Array asociativo con la $ruta y $archivo encontrados en el directorio

En la página PHP podemos llamar a la función recursiva por primera vez con el directorio que queremos leer y nos devolvera al Array asociativo con la $ruta y $archivo encontrados. Al mismo tiempo que ejecuta la función mostrará un listado <ul> con los directorios y archivos que encuentre.

Podemos obtener por separado cada directorio y archivo recorriendo el Array devuelto por la función y he añadido la función var_dump() para mostrar la estructura interna asociativa del Array.

Espero que esta función y su explicación os sea de utilidad y mostrar un listado <ul> es una alternativa visual que se puede dejar o quitar a gusto de cada uno.

¡ Espero que este artículo sea de vuestro interés !

Deja un comentario