Finder : Recherche de fichiers
Vous avez besoin de trouver des fichiers correspondant à un certain masque ? Le Finder peut vous aider. Il s'agit d'un outil polyvalent et rapide pour parcourir la structure des répertoires.
Installation :
composer require nette/utils
Les exemples supposent qu'un alias a été créé :
use Nette\Utils\Finder;
Utilisation de
Tout d'abord, voyons comment vous pouvez utiliser Nette\Utils\Finder pour lister les noms de fichiers avec les
extensions .txt
et .md
dans le répertoire actuel :
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
echo $file;
}
Le répertoire par défaut pour la recherche est le répertoire courant, mais vous pouvez le changer en utilisant les méthodes
in() ou from(). La variable $file
est une instance de la classe FileInfo avec de nombreuses méthodes utiles. La clé $name
contient le chemin d'accès au
fichier sous forme de chaîne.
Que rechercher ?
En plus de la méthode findFiles()
, il existe également findDirectories()
, qui ne recherche que les
répertoires, et find()
, qui recherche les deux. Ces méthodes sont statiques, elles peuvent donc être appelées
sans créer d'instance. Le paramètre mask est facultatif, si vous ne le spécifiez pas, tout est recherché.
foreach (Finder::find() as $file) {
echo $file; // maintenant tous les fichiers et répertoires sont listés
}
Utilisez les méthodes files()
et directories()
pour ajouter ce qui doit être recherché. Ces
méthodes peuvent être appelées à plusieurs reprises et un tableau de masques peut être fourni en tant que paramètre :
Finder::findDirectories('vendor') // tous les répertoires
->files(['*.php', '*.phpt']); // plus tous les fichiers PHP
Une alternative aux méthodes statiques est de créer une instance à l'aide de new Finder
(l'objet frais créé
de cette façon ne cherche rien) et de spécifier ce qu'il faut rechercher à l'aide de files()
et
directories()
:
(new Finder)
->directories() // tous les répertoires
->files('*.php'); // plus tous les fichiers PHP
Vous pouvez utiliser des caractères génériques *
, **
, ?
and [...]
dans le masque. Vous pouvez même spécifier des répertoires, par exemple src/*.php
recherchera tous les fichiers PHP dans le répertoire src
.
Les liens symboliques sont également considérés comme des répertoires ou des fichiers.
Où chercher ?
Le répertoire de recherche par défaut est le répertoire courant. Vous pouvez le modifier en utilisant les méthodes
in()
et from()
. Comme vous pouvez le constater d'après les noms des méthodes, in()
ne
recherche que dans le répertoire courant, tandis que from()
recherche également dans ses sous-répertoires (de
manière récursive). Si vous souhaitez effectuer une recherche récursive dans le répertoire courant, vous pouvez utiliser
from('.')
.
Ces méthodes peuvent être appelées plusieurs fois ou vous pouvez leur passer plusieurs chemins sous forme de tableaux, les
fichiers seront alors recherchés dans tous les répertoires. Si l'un des répertoires n'existe pas, un message d'erreur (
Nette\UnexpectedValueException
) est lancé.
Finder::findFiles('*.php')
->in(['src', 'tests']) // recherche directement dans src/ et tests/
->from('vendor'); // recherche également dans les sous-répertoires vendor/
Les chemins relatifs sont relatifs au répertoire actuel. Bien sûr, des chemins absolus peuvent également être spécifiés :
Finder::findFiles('*.php')
->in('/var/www/html');
Les caractères génériques *
, **
, ?
can be used in the
path. For example, you can use the path src/*/*.php
pour rechercher tous les fichiers PHP dans les répertoires de
deuxième niveau du répertoire src
. Le caractère **
, appelé globstar, est un atout puissant car il
vous permet de rechercher également dans les sous-répertoires : utilisez src/**/tests/*.php
pour rechercher tous
les fichiers PHP du répertoire tests
situés dans src
ou n'importe lequel de ses sous-répertoires.
D'autre part, les caractères de remplacement [...]
ne sont pas pris en charge dans le chemin d'accès,
c'est-à-dire qu'ils n'ont pas de signification particulière pour éviter tout comportement indésirable dans le cas où vous
recherchez par exemple in(__DIR__)
et que par hasard les caractères []
apparaissent dans le chemin
d'accès.
Lors d'une recherche approfondie de fichiers et de répertoires, le répertoire parent est renvoyé en premier et ensuite les
fichiers qu'il contient, ce qui peut être inversé avec childFirst()
.
Caractères génériques
Vous pouvez utiliser plusieurs caractères spéciaux dans le masque :
*
– replaces any number of arbitrary characters (except/
)**
– remplace un nombre quelconque de caractères arbitraires, y compris/
(c'est-à-dire qu'il peut être recherché sur plusieurs niveaux)?
– replaces one arbitrary character (except/
)[a-z]
– remplace un caractère de la liste de caractères entre crochets.[!a-z]
– remplace un caractère en dehors de la liste de caractères entre crochets
Exemples d'utilisation :
img/?.png
– fichiers avec le nom à une lettre0.png
,1.png
,x.png
, etc.logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log
– fichiers journaux au formatYYYY-MM-DD
src/**/tests/*
– fichiers dans le répertoiresrc/tests
,src/foo/tests
,src/foo/bar/tests
et ainsi de suite.docs/**.md
– tous les fichiers avec l'extension.md
dans tous les sous-répertoires du répertoiredocs
A l'exception de
Utilisez la méthode exclude()
pour exclure des fichiers et des répertoires des recherches. Vous spécifiez un
masque auquel le fichier ne doit pas correspondre. Exemple de recherche de fichiers *.txt
à l'exception de ceux
contenant la lettre X
dans le nom :
Finder::findFiles('*.txt')
->exclude('*X*');
Utilisez exclude()
pour ignorer les sous-répertoires parcourus :
Finder::findFiles('*.php')
->from($dir)
->exclude('temp', '.git')
Filtrage de
Le Finder propose plusieurs méthodes pour filtrer les résultats (c'est-à-dire les réduire). Vous pouvez les combiner et les appeler à plusieurs reprises.
Utilisez size()
pour filtrer par taille de fichier. De cette façon, nous trouvons les fichiers dont la taille est
comprise entre 100 et 200 octets :
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200);
La méthode date()
permet de filtrer par la date de la dernière modification du fichier. Les valeurs peuvent
être absolues ou relatives à la date et à l'heure actuelles. Par exemple, voici comment trouver les fichiers modifiés au cours
des deux dernières semaines :
Finder::findFiles('*.php')
->date('>', '-2 weeks')
->from($dir)
Les deux fonctions comprennent les opérateurs >
, >=
, <
, <=
,
=
, !=
, <>
.
Le Finder vous permet également de filtrer les résultats à l'aide de fonctions personnalisées. La fonction reçoit un objet
Nette\Utils\FileInfo
comme paramètre et doit retourner true
pour inclure le fichier dans les
résultats.
Exemple : rechercher les fichiers PHP qui contiennent la chaîne de caractères Nette
(insensible à la
casse) :
Finder::findFiles('*.php')
->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
Filtrage en profondeur
Lors d'une recherche récursive, vous pouvez définir la profondeur d'exploration maximale à l'aide de la méthode
limitDepth()
. Si vous définissez limitDepth(1)
, seuls les premiers sous-répertoires sont explorés,
limitDepth(0)
désactive l'exploration en profondeur, et une valeur de –1 annule la limite.
Le Finder vous permet d'utiliser ses propres fonctions pour décider du répertoire à pénétrer lors de l'exploration. La
fonction reçoit un objet Nette\Utils\FileInfo
comme paramètre et doit retourner true
pour entrer dans
le répertoire :
Finder::findFiles('*.php')
->descentFilter($file->getBasename() !== 'temp');
Triage
Le Finder offre également plusieurs fonctions permettant de trier les résultats.
La méthode sortByName()
trie les résultats par nom de fichier. Le tri est naturel, c'est-à-dire qu'il traite
correctement les chiffres dans les noms et renvoie par exemple foo1.txt
avant foo10.txt
.
Le Finder vous permet également de trier en utilisant une fonction personnalisée. Elle prend deux objets
Nette\Utils\FileInfo
comme paramètres et doit retourner le résultat de la comparaison avec l'opérateur
<=>
c'est-à-dire -1
, 0
nebo 1
. Par exemple, voici comment trier les
fichiers par taille :
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
Plusieurs recherches différentes
Si vous devez trouver plusieurs fichiers différents dans des endroits différents ou répondant à des critères différents,
utilisez la méthode append()
. Elle renvoie un nouvel objet Finder
afin que vous puissiez enchaîner les
appels de méthode :
($finder = new Finder) // enregistre le premier Finder dans la variable $finder !
->files('*.php') // recherche les fichiers *.php dans src/
->from('src')
->append()
->files('*.md') // dans docs/ recherche les fichiers *.md
->from('docs')
->append()
->files('*.json'); // dans le dossier actuel, recherche des fichiers *.json
Alternativement, vous pouvez utiliser la méthode append()
pour ajouter un fichier spécifique (ou un tableau de
fichiers). Elle renvoie alors le même objet Finder
:
$finder = Finder::findFiles('*.txt')
->append(__FILE__);
FileInfo
Nette\Utils\FileInfo est une classe représentant un fichier ou un répertoire dans les résultats de recherche. Il s'agit d'une extension de la classe SplFileInfo qui fournit des informations telles que la taille du fichier, la date de dernière modification, le nom, le chemin, etc.
De plus, elle fournit des méthodes pour renvoyer les chemins relatifs, ce qui est utile lors d'une navigation en profondeur :
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
$absoluteFilePath = $file->getRealPath();
$relativeFilePath = $file->getRelativePathname();
}
Vous disposez également de méthodes pour lire et écrire le contenu d'un fichier :
foreach ($finder as $file) {
$contents = $file->read();
// ...
$file->write($contents);
}
Renvoyer les résultats sous forme de tableau
Comme nous l'avons vu dans les exemples, le Finder implémente l'interface IteratorAggregate
, ce qui vous permet
d'utiliser foreach
pour parcourir les résultats. Il est programmé de manière à ce que les résultats ne soient
chargés qu'au fur et à mesure de la navigation, donc si vous avez un grand nombre de fichiers, il n'attend pas qu'ils soient
tous lus.
Vous pouvez également obtenir les résultats sous la forme d'un tableau d'objets Nette\Utils\FileInfo
, en
utilisant la méthode collect()
. Le tableau n'est pas associatif, mais numérique.
$array = $finder->findFiles('*.php')->collect();