Kereső: Fájlkeresés
Meg kell találnia egy bizonyos maszknak megfelelő fájlokat? A Finder segíthet. Ez egy sokoldalú és gyors eszköz a könyvtárstruktúra böngészésére.
Telepítés:
composer require nette/utils
A példák feltételezik egy alias létrehozását:
use Nette\Utils\Finder;
A használata
Először is nézzük meg, hogyan használhatjuk a Nette\Utils\Finder programot a .txt
és
.md
kiterjesztésű fájlnevek listázására az aktuális könyvtárban:
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
echo $file;
}
A keresés alapértelmezett könyvtára az aktuális könyvtár, de ezt az in() vagy from()
metódusokkal megváltoztathatjuk. A $file
változó a FileInfo osztály egy példánya,
amely sok hasznos metódussal rendelkezik. A $name
kulcs a fájl elérési útvonalát tartalmazza sztringként.
Mit keressünk?
A findFiles()
módszer mellett létezik a findDirectories()
, amely csak a könyvtárakban keres, és
a find()
, amely mindkettőben keres. Ezek a metódusok statikusak, tehát példány létrehozása nélkül
hívhatók. A maszk paraméter opcionális, ha nem adjuk meg, mindent átkutat.
foreach (Finder::find() as $file) {
echo $file; // most már minden fájl és könyvtár fel van sorolva.
}
A files()
és a directories()
metódusokkal adhatjuk meg, hogy mit keressünk még. A metódusok
ismételten meghívhatók, és paraméterként megadható a maszkok tömbje:
Finder::findDirectories('vendor') // az összes könyvtárat
->files(['*.php', '*.phpt']); // valamint az összes PHP fájl
A statikus módszerek alternatívája, hogy létrehozunk egy példányt a new Finder
segítségével (az így
létrehozott friss objektum nem keres semmit), és megadjuk, hogy mit keressünk a files()
és a
directories()
segítségével:
(new Finder)
->directories() // az összes könyvtárat
->files('*.php'); // valamint az összes PHP fájl
Használhat vadkártyákat *
, **
, ?
and [...]
a maszkban. Megadhat könyvtárakat is, például a src/*.php
a src
könyvtárban található összes
PHP-fájlt megkeresi.
A szimbolikus hivatkozások szintén könyvtáraknak vagy fájloknak minősülnek.
Hol keressünk?
Az alapértelmezett keresési könyvtár az aktuális könyvtár. Ezt a in()
és a from()
módszerekkel módosíthatja. Amint a metódusnevekből látható, a in()
csak az aktuális könyvtárban keres, míg
a from()
annak alkönyvtáraiban is (rekurzívan). Ha rekurzívan akarsz keresni az aktuális könyvtárban,
használhatod a from('.')
.
Ezeket a metódusokat többször is meg lehet hívni, vagy több elérési utat is átadhatunk nekik tömbként, akkor a
fájlok minden könyvtárban keresésre kerülnek. Ha az egyik könyvtár nem létezik, akkor a
Nette\UnexpectedValueException
eredményt kapjuk.
Finder::findFiles('*.php')
->in(['src', 'tests']) // közvetlenül a src/ és tests/ fájlokban keres.
->from('vendor'); // keres a vendor/ alkönyvtárakban is
A relatív elérési utak az aktuális könyvtárhoz képest relatívak. Természetesen abszolút elérési utak is megadhatók:
Finder::findFiles('*.php')
->in('/var/www/html');
Wildcards wildcards *
, **
, ?
can be used in the path. For
example, you can use the path src/*/*.php
a src
könyvtár második szintű könyvtáraiban található
összes PHP fájl kereséséhez. A **
karakter, az úgynevezett globstar egy erős aduász, mert lehetővé teszi az
alkönyvtárakban való keresést is: a src/**/tests/*.php
használatával a tests
könyvtárban
található összes PHP-fájlt kereshetjük, amelyek a src
könyvtárban vagy annak bármelyik alkönyvtárában
találhatók.
Másrészt a jokerek [...]
karakterek nem támogatottak az elérési útvonalban, azaz nincs speciális
jelentésük, hogy elkerüljük a nem kívánt viselkedést abban az esetben, ha például a in(__DIR__)
címre
keresünk, és véletlenül []
karakterek jelennek meg az elérési útvonalban.
A fájlok és könyvtárak mélységi keresésekor a rendszer először a szülő könyvtárat adja vissza, majd az abban
található fájlokat, ami a childFirst()
segítségével megfordítható.
Jokerjelek
A maszkban több speciális karaktert is használhat:
*
– replaces any number of arbitrary characters (except/
)**
– tetszőleges számú tetszőleges karaktert helyettesít, beleértve a/
-t is (azaz többszintű keresés is lehetséges).?
– replaces one arbitrary character (except/
)[a-z]
– egy karaktert helyettesít a szögletes zárójelben lévő karakterek listájából.[!a-z]
– egy karaktert helyettesít a szögletes zárójelben lévő karakterek listáján kívül.
Használati példák:
img/?.png
–0.png
,1.png
,x.png
, stb.logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log
– naplófájlok a következő formátumbanYYYY-MM-DD
src/**/tests/*
– asrc/tests
,src/foo/tests
,src/foo/bar/tests
stb. könyvtárban található fájlok.docs/**.md
– a.md
kiterjesztésű összes fájl a könyvtár összes alkönyvtárában.docs
A kivételével.
A exclude()
módszerrel kizárhat fájlokat és könyvtárakat a keresésből. Megad egy maszkot, amelynek a fájl
nem felelhet meg. Példa a *.txt
fájlok keresésére, kivéve azokat, amelyek nevében szerepel az
X
betű:
Finder::findFiles('*.txt')
->exclude('*X*');
A exclude()
használatával kihagyhatja a böngészett alkönyvtárakat:
Finder::findFiles('*.php')
->from($dir)
->exclude('temp', '.git')
Szűrés:
A Finder többféle módszert kínál a találatok szűrésére (azaz csökkentésére). Ezeket kombinálhatja és többször is meghívhatja.
A size()
segítségével szűrhet a fájlméret szerint. Így a 100 és 200 bájt közötti méretű fájlokat
találjuk meg:
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200);
A date()
módszer a fájl utolsó módosításának dátuma alapján szűr. Az értékek lehetnek abszolút vagy
az aktuális dátumhoz és időhöz viszonyítottak, például így találjuk meg az elmúlt két hétben módosított
fájlokat:
Finder::findFiles('*.php')
->date('>', '-2 weeks')
->from($dir)
Mindkét függvény érti a >
, >=
, <
, <=
, =
,
!=
, <>
operátorokat.
A Finder lehetővé teszi az eredmények szűrését egyéni függvények segítségével is. A függvény paraméterként
egy Nette\Utils\FileInfo
objektumot kap, és vissza kell adnia a true
címet ahhoz, hogy a fájl
bekerüljön az eredmények közé.
Példa: A Nette
karakterláncot tartalmazó PHP-fájlok keresése (nagy- és kisbetűket nem érzékeny):
Finder::findFiles('*.php')
->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
Mélységi szűrés
Rekurzív keresés esetén a limitDepth()
módszerrel beállíthatja a maximális feltérképezési mélységet. A
limitDepth(1)
beállítása esetén csak az első alkönyvtárak kerülnek feltérképezésre, a
limitDepth(0)
letiltja a mélységi feltérképezést, a –1 érték pedig törli a korlátozást.
A Finder lehetővé teszi, hogy saját függvényei segítségével döntse el, melyik könyvtárba lépjen be a böngészés
során. A függvény paraméterként egy Nette\Utils\FileInfo
objektumot kap, és a könyvtárba való belépéshez
vissza kell adnia a true
értéket:
Finder::findFiles('*.php')
->descentFilter($file->getBasename() !== 'temp');
Rendezés
A Finder több funkciót is kínál az eredmények rendezésére.
A sortByName()
módszer az eredményeket fájlnév szerint rendezi. A rendezés természetes, azaz helyesen
kezeli a nevekben szereplő számokat, és például a foo1.txt
-t a foo10.txt
előtt adja vissza.
A Finder lehetővé teszi az egyéni funkcióval történő rendezést is. Ez két Nette\Utils\FileInfo
objektumot vesz fel paraméterként, és az összehasonlítás eredményét kell visszaadnia az operátorral
<=>
, azaz -1
, 0
nebo 1
. Például így rendezzük a fájlokat méret
szerint:
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
Több különböző keresés
Ha több különböző helyen lévő vagy különböző feltételeknek megfelelő fájlt kell keresnie, használja a
append()
módszert. Ez egy új Finder
objektumot ad vissza, így a metódushívások láncolhatók:
($finder = new Finder) // tároljuk az első Finder-t a $finder változóban!
->files('*.php') // *.php fájlokat keresünk a src/ könyvtárban.
->from('src')
->append()
->files('*.md') // a docs/-ban keres *.md fájlokat
->from('docs')
->append()
->files('*.json'); // az aktuális mappában keressük a *.json fájlokat.
Alternatívaként használhatja a append()
metódust egy adott fájl (vagy fájlok tömbjének) hozzáadásához.
Ekkor ugyanazt az objektumot adja vissza Finder
:
$finder = Finder::findFiles('*.txt')
->append(__FILE__);
FileInfo
ANette\Utils\FileInfo egy osztály, amely egy fájlt vagy könyvtárat reprezentál a keresési eredményekben. Ez a SplFileInfo osztály kiterjesztése, amely olyan információkat szolgáltat, mint a fájl mérete, utolsó módosítás dátuma, neve, elérési útja stb.
Ezen kívül metódusokat biztosít a relatív elérési utak visszaadására, ami hasznos a mélységi böngészés során:
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
$absoluteFilePath = $file->getRealPath();
$relativeFilePath = $file->getRelativePathname();
}
Vannak módszerei a fájl tartalmának olvasására és írására is:
foreach ($finder as $file) {
$contents = $file->read();
// ...
$file->write($contents);
}
Eredmények visszaadása tömbként
Amint a példákban láttuk, a Finder megvalósítja a IteratorAggregate
interfészt , így a foreach
segítségével böngészhetünk az eredmények között. Úgy van programozva, hogy az eredmények csak a böngészés közben
töltődnek be, így ha nagyszámú fájlod van, nem várja meg, hogy mindet beolvassa.
A collect()
metódus segítségével az eredményeket Nette\Utils\FileInfo
objektumok tömbjeként is
visszakaphatja. A tömb nem asszociatív, hanem numerikus.
$array = $finder->findFiles('*.php')->collect();