El componente Finder

El componente Finder busca archivos y directorios a través de una sencilla e intuitiva interfaz.

Instalando

Puedes instalar el componente de varias maneras diferentes:

Usando

La clase Symfony\Component\Finder\Finder busca archivos y/o directorios:

use Symfony\Component\Finder\Finder;

$finder = new Finder();
$finder->files()->in(__DIR__);

foreach ($finder as $file) {
    // Imprime la ruta absoluta
    print $file->getRealpath()."\n";

    // Imprime la ruta relativa al archivo, omitiendo el nombre de archivo
    print $file->getRelativePath()."\n";

    // Imprime la ruta relativa para el archivo
    print $file->getRelativePathname()."\n";
}

$file es una instancia de Symfony\Component\Finder\SplFileInfo la cual extiende a SplFileInfo para proporcionar métodos para trabajar con rutas relativas.

El código anterior imprime recursivamente los nombres de todos los archivos en el directorio actual. La clase Finder utiliza una interfaz fluida, por lo que todos los métodos devuelven la instancia del Finder.

Truco

Una instancia del Finder es un Iterator de PHP. Por lo tanto, en lugar de iterar sobre el Finder con foreach, también lo puedes convertir en un arreglo con el método iterator_to_array u obtener el número de elementos con iterator_count.

Prudencia

Al buscar a través de múltiples ubicaciones pasadas al método in(), internamente se crea un iterador independiente por cada ubicación. Esto significa que tienes múltiples resultados agregados a uno. Debido a que iterator_to_array de manera predefinida usa el conjunto de claves del resultado, al convertirlo en arreglo, algunas claves se podrían duplicar y por lo tanto sustituir sus valores. Esto se puede evitar pasando false como segundo argumento a iterator_to_array.

Criterios

Hay muchas maneras de filtrar y ordenar tu resultado.

Ubicación

La ubicación es el único criterio obligatorio. Este dice al buscador cual directorio utilizar para la búsqueda:

$finder->in(__DIR__);

Busca en varios lugares encadenando llamadas al método in():

$finder->files()->in(__DIR__)->in('/elsewhere');

Nuevo en la versión 2.2: El soporte necesario para el comodín se añadió en la versión 2.2.

Usa caracteres comodín para buscar en los directorios que emparejen un patrón:

$finder->in('src/Symfony/*/*/Resources');

Cada patrón tiene que resolver cuando menos con una ruta de directorio.

Excluye directorios coincidentes con el método exclude():

$finder->in(__DIR__)->exclude('ruby');

Debido a que Finder utiliza iteradores PHP, puedes pasar cualquier URL con un protocolo compatible:

$finder->in('ftp://ejemplo.com/pub/');

Y también trabaja con flujos definidos por el usuario:

use Symfony\Component\Finder\Finder;

$s3 = new \Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper("s3");

$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
    // ... hace algo

    print $file->getFilename()."\n";
}

Nota

Lee la documentación de Flujos para aprender a crear tus propios flujos.

Archivos o directorios

De manera predeterminada, Finder devuelve archivos y directorios; Pero los métodos files() y directories() controlan:

$finder->files();

$finder->directories();

Si quieres seguir los enlaces, utiliza el método followLinks():

$finder->files()->followLinks();

De forma predeterminada, el iterador ignora archivos VCS populares. Esto se puede cambiar con el método ignoreVCS():

$finder->ignoreVCS(false);

Ordenación

Ordena el resultado por nombre o por tipo (primero directorios, luego archivos):

$finder->sortByName();

$finder->sortByType();

Nota

Ten en cuenta que los métodos sort* necesitan obtener todos los elementos para hacer su trabajo. Para iteradores grandes, es lento.

También puedes definir tu propio algoritmo de ordenación con el método sort():

$sort = function (\SplFileInfo $a, \SplFileInfo $b)
{
    return strcmp($a->getRealpath(), $b->getRealpath());
};

$finder->sort($sort);

Nombre de archivo

Filtra archivos por nombre con el método name():

$finder->files()->name('*.php');

El método name() acepta globos, cadenas o expresiones regulares:

$finder->files()->name('/\.php$/');

El método notName() excluye archivos coincidentes con un patrón:

$finder->files()->notName('*.rb');

Contenido del archivo

Nuevo en la versión 2.1: Los métodos contains() y notContains() se añadieron en la versión 2.1

Restringiendo el contenido de archivos con el método contains():

$finder->files()->contains('lorem ipsum');

El método contains() acepta cadenas o expresiones regulares:

$finder->files()->contains('/lorem\s+ipsum$/i');

El método notContains() excluye archivos que contienen un determinado patrón:

$finder->files()->notContains('dolor sit amet');

path

Nuevo en la versión 2.2: Los métodos path() y notPath() se añadieron en la versión 2.2.

Restringe archivos y directorios por ruta con el método path():

$finder->path('some/special/dir');

En todos los ambientes se debería usar la barra inclinada (es decir, /) como separador de directorio.

El el método path() acepta una cadena o una expresión regular:

$finder->path('foo/bar');
$finder->path('/^foo\/bar/');

Internamente, las cadenas se convierten a expresiones regulares escapando las barras invertidas y añadiendo delimitadores:

dirname    ===>    /dirname/
a/b/c      ===>    /a\/b\/c/

El método notPath() excluye archivos por ruta:

$finder->notPath('otro/dir');

Tamaño de archivo

Filtra archivos por tamaño con el método size():

$finder->files()->size('< 1.5K');

Filtra por rangos de tamaño encadenando llamadas a:

$finder->files()->size('>= 1K')->size('<= 2K');

El operador de comparación puede ser cualquiera de los siguientes: >, >=, <, <=, ==, !=.

Nuevo en la versión 2.1: El operador != se añadió en la versión 2.1.

El valor destino puede utilizar magnitudes de kilobytes (k, ki), megabytes (m, mi), o gigabytes (g, gi). Los sufijos con una i usan la versión 2**n adecuada de acuerdo al estándar IEC.

Fecha de archivo

Filtra archivos por fecha de última modificación con el método date():

$finder->date('since yesterday');

El operador de comparación puede ser cualquiera de los siguientes: >, >=, <, <=, ==. También puedes utilizar since o after como alias para >, y until o before como alias para <.

El valor destino puede ser cualquier fecha compatible con la función strtotime.

Profundidad de directorio

De manera predeterminada, Finder recorre directorios recurrentemente. Filtra la profundidad del recorrido con el método depth():

$finder->depth('== 0');
$finder->depth('< 3');

Filtrado personalizado

Para restringir que el archivo coincida con su propia estrategia, utiliza el método filter():

$filter = function (\SplFileInfo $file)
{
    if (strlen($file) > 10) {
            return false;
    }
};

$finder->files()->filter($filtro);

El método filter() toma un cierre como argumento. Por cada archivo coincidente, este es invocado con el archivo como una instancia de Symfony\Component\Finder\SplFileInfo. El archivo se excluye del conjunto de resultados si el cierre devuelve false.

Leyendo el contenido de los archivos devueltos

Nuevo en la versión 2.1: El método getContents() se introdujo en la versión 2.1.

El contenido devuelto de los archivos se puede leer con el método getContents():

use Symfony\Component\Finder\Finder;

$finder = new Finder();
$finder->files()->in(__DIR__);

foreach ($finder as $file) {
    $contents = $file->getContents();
    ...
}
Bifúrcame en GitHub