Iskalnik: Iskanje datotek
Potrebujete najti datoteke, ki ustrezajo določeni maski? Iskalnik vam lahko pomaga. Je vsestransko in hitro orodje za pregledovanje strukture imenikov.
Namestitev:
composer require nette/utils
Primeri predpostavljajo, da je bil ustvarjen vzdevek:
use Nette\Utils\Finder;
Uporaba
Najprej si oglejmo, kako lahko s pomočjo Nette\Utils\Finder izpišete imena datotek s končnicama
.txt
in .md
v trenutnem imeniku:
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
echo $file;
}
Privzet imenik za iskanje je trenutni imenik, vendar ga lahko spremenite z uporabo metod in()
ali from( ). Spremenljivka $file
je primerek razreda FileInfo z veliko uporabnimi
metodami. Ključ $name
vsebuje pot do datoteke kot niz.
Kaj iskati?
Poleg metode findFiles()
obstajata še findDirectories()
, ki išče samo po imenikih, in
find()
, ki išče po obeh. Ti metodi sta statični, zato ju lahko kličete, ne da bi ustvarili primerek. Parameter
maska ni obvezen, če ga ne navedete, se poišče vse.
foreach (Finder::find() as $file) {
echo $file; // zdaj so na seznamu vse datoteke in imeniki
}
Z metodama files()
in directories()
lahko dodate, kaj naj se še išče. Metodi lahko pokličete
večkrat, kot parameter pa lahko navedete polje mask:
Finder::findDirectories('vendor') // vsi imeniki
->files(['*.php', '*.phpt']); // ter vse datoteke PHP
Alternativa statičnim metodam je, da ustvarite primerek z uporabo new Finder
(tako ustvarjen svež objekt ne
išče ničesar) in določite, kaj naj se išče, z uporabo files()
in directories()
:
(new Finder)
->directories() // vsi imeniki
->files('*.php'); // ter vse datoteke PHP
Uporabite lahko nadomestne znake *
, **
, ?
and
[...]
v maski. Navedete lahko celo imenike, na primer src/*.php
bo poiskal vse datoteke PHP v imeniku
src
.
Za imenike ali datoteke se štejejo tudi simelne povezave.
Kje iskati?
Privzet imenik za iskanje je trenutni imenik. To lahko spremenite z uporabo metod in()
in from()
.
Kot je razvidno iz imen metod, in()
išče samo po trenutnem imeniku, medtem ko from()
išče tudi po
njegovih podimenikih (rekurzivno). Če želite rekurzivno iskati v trenutnem imeniku, lahko uporabite from('.')
.
Ti metodi lahko pokličete večkrat ali pa jima posredujete več poti kot polja, potem se bodo datoteke iskale v vseh
imenikih. Če eden od imenikov ne obstaja, se vrže sporočilo Nette\UnexpectedValueException
.
Finder::findFiles('*.php')
->in(['src', 'tests']) // išče neposredno v src/ in tests/
->from('vendor'); // išče tudi v podimenikih vendor/
Relativne poti so relativne glede na trenutni imenik. Seveda lahko določite tudi absolutne poti:
Finder::findFiles('*.php')
->in('/var/www/html');
*
, **
, ?
can be used in the path. For example, you can use the path
src/*/*.php
za iskanje vseh datotek PHP v imenikih druge ravni v imeniku
src
. Znak **
, imenovan globstar, je močan adut, saj omogoča iskanje tudi po podimenikih: uporabite
src/**/tests/*.php
za iskanje vseh datotek PHP v imeniku tests
, ki se nahajajo v imeniku
src
ali katerem koli njegovem podimeniku.
Po drugi strani pa so nadomestni znaki [...]
znaki v poti niso podprti, tj. nimajo posebnega pomena, da bi se
izognili nezaželenemu obnašanju v primeru, da iščete na primer in(__DIR__)
in se po naključju v poti pojavijo
znaki []
.
Pri poglobljenem iskanju datotek in imenikov se najprej vrne nadrejeni imenik, nato pa datoteke, ki jih vsebuje, kar lahko
obrnete s childFirst()
.
Zaščitni znaki
V maski lahko uporabite več posebnih znakov:
*
– replaces any number of arbitrary characters (except/
)**
– nadomesti poljubno število poljubnih znakov, vključno z/
(tj. lahko se išče na več ravneh)?
– replaces one arbitrary character (except/
)[a-z]
– nadomesti en znak s seznama znakov v oglatih oklepajih[!a-z]
– nadomesti en znak zunaj seznama znakov v oglatih oklepajih
Primeri uporabe:
img/?.png
– datoteke z enočrkovnim imenom0.png
,1.png
,x.png
, itd.logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log
– dnevniške datoteke v oblikiYYYY-MM-DD
src/**/tests/*
– datoteke v imenikusrc/tests
,src/foo/tests
,src/foo/bar/tests
itd.docs/**.md
– vse datoteke s končnico.md
v vseh podimenikih imenika.docs
Z izjemo
Za izključitev datotek in imenikov iz iskanja uporabite metodo exclude()
. Določite masko, ki ji datoteka ne sme
ustrezati. Primer iskanja datotek *.txt
, razen tistih, ki v imenu vsebujejo črko X
:
Finder::findFiles('*.txt')
->exclude('*X*');
Uporabite exclude()
, če želite preskočiti pregledane podimenike:
Finder::findFiles('*.php')
->from($dir)
->exclude('temp', '.git')
Filtriranje
Iskalnik ponuja več načinov za filtriranje rezultatov (tj. njihovo zmanjševanje). Te metode lahko kombinirate in jih večkrat prikličete.
Za filtriranje po velikosti datoteke uporabite size()
. Na ta način poiščemo datoteke z velikostjo med 100 in
200 bajti:
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200);
Metoda date()
filtrira po datumu zadnje spremembe datoteke. Vrednosti so lahko absolutne ali relativne glede na
trenutni datum in čas, tako na primer najdemo datoteke, spremenjene v zadnjih dveh tednih:
Finder::findFiles('*.php')
->date('>', '-2 weeks')
->from($dir)
Obe funkciji razumeta operatorje >
, >=
, <
, <=
, =
,
!=
, <>
.
Iskalnik omogoča tudi filtriranje rezultatov z uporabo funkcij po meri. Funkcija prejme kot parameter objekt
Nette\Utils\FileInfo
in mora vrniti true
, da se datoteka vključi v rezultate.
Primer: poiščite datoteke PHP, ki vsebujejo niz Nette
(brez upoštevanja velikih in malih črk):
Finder::findFiles('*.php')
->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
Globinsko filtriranje
Pri rekurzivnem iskanju lahko največjo globino iskanja nastavite z metodo limitDepth()
. Če nastavite
limitDepth(1)
, se prečešejo samo prvi podimeniki, limitDepth(0)
onemogoči globinsko pregledovanje,
vrednost –1 pa omejitev prekliče.
Iskalnik omogoča uporabo lastnih funkcij za odločanje o tem, v kateri imenik naj vstopite pri brskanju. Funkcija prejme kot
parameter objekt Nette\Utils\FileInfo
in mora vrniti true
, da vstopi v imenik:
Finder::findFiles('*.php')
->descentFilter($file->getBasename() !== 'temp');
Razvrščanje
Iskalnik ponuja tudi več funkcij za razvrščanje rezultatov.
Metoda sortByName()
razvršča rezultate po imenu datoteke. Sortiranje je naravno, tj. pravilno obravnava
številke v imenih in vrne npr. foo1.txt
pred foo10.txt
.
Iskalnik omogoča tudi razvrščanje z uporabo funkcije po meri. Ta kot parametra sprejme dva predmeta
Nette\Utils\FileInfo
in mora vrniti rezultat primerjave z operatorjem <=>
, tj. -1
,
0
nebo 1
. Tako na primer razvrstimo datoteke po velikosti:
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
Več različnih iskanj
Če morate poiskati več različnih datotek na različnih lokacijah ali ki izpolnjujejo različna merila, uporabite metodo
append()
. Ta vrne nov objekt Finder
, tako da lahko verižno kličete metode:
($finder = new Finder) // shranite prvi iskalnik v spremenljivko $finder!
->files('*.php') // iskanje datotek *.php v src/
->from('src')
->append()
->files('*.md') // v docs/ poiščite datoteke *.md
->from('docs')
->append()
->files('*.json'); // v trenutni mapi poiščite datoteke *.json
Lahko pa uporabite tudi metodo append()
za dodajanje določene datoteke (ali niza datotek). Nato vrne isti predmet
Finder
:
$finder = Finder::findFiles('*.txt')
->append(__FILE__);
FileInfo
Nette\Utils\FileInfo je razred, ki predstavlja datoteko ali imenik v rezultatih iskanja. Je razširitev razreda SplFileInfo, ki zagotavlja informacije, kot so velikost datoteke, datum zadnje spremembe, ime, pot itd.
Poleg tega zagotavlja metode za vračanje relativnih poti, kar je uporabno pri poglobljenem iskanju:
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
$absoluteFilePath = $file->getRealPath();
$relativeFilePath = $file->getRelativePathname();
}
Na voljo so tudi metode za branje in pisanje vsebine datoteke:
foreach ($finder as $file) {
$contents = $file->read();
// ...
$file->write($contents);
}
Vračanje rezultatov v obliki polja
Kot je razvidno iz primerov, iskalnik implementira vmesnik IteratorAggregate
, zato lahko za brskanje po rezultatih
uporabite foreach
. Programiran je tako, da se rezultati nalagajo šele med brskanjem, tako da če imate veliko
število datotek, ne čaka, da se vse preberejo.
Rezultate lahko vrnete tudi kot polje predmetov Nette\Utils\FileInfo
z uporabo metode collect()
.
Polje ni asociativno, temveč številsko.
$array = $finder->findFiles('*.php')->collect();