Finder: Dosya Arama
Belirli bir maskeyle eşleşen dosyaları mı bulmanız gerekiyor? Finder size yardımcı olabilir. Dizin yapısına göz atmak için çok yönlü ve hızlı bir araçtır.
Kurulum:
composer require nette/utils
Örneklerde bir takma ad oluşturulduğu varsayılmaktadır:
use Nette\Utils\Finder;
Kullanma
İlk olarak, geçerli dizindeki .txt
ve .md
uzantılı dosya adlarını listelemek için Nette\Utils\Finder adresini nasıl kullanabileceğinizi
görelim:
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
echo $file;
}
Arama için varsayılan dizin geçerli dizindir, ancak in() veya from() yöntemlerini
kullanarak bunu değiştirebilirsiniz. $file
değişkeni, birçok yararlı yöntemi olan FileInfo sınıfının bir örneğidir. $name
anahtarı, dosyanın yolunu bir dize olarak
içerir.
Ne Aranmalı?
findFiles()
yöntemine ek olarak, yalnızca dizinleri arayan findDirectories()
ve her ikisini de
arayan find()
yöntemleri de vardır. Bu yöntemler statiktir, yani bir örnek oluşturmadan çağrılabilirler.
Maske parametresi isteğe bağlıdır, belirtmezseniz her şey aranır.
foreach (Finder::find() as $file) {
echo $file; // şimdi tüm dosyalar ve dizinler listeleniyor
}
Başka nelerin aranacağını eklemek için files()
ve directories()
yöntemlerini kullanın.
Yöntemler tekrar tekrar çağrılabilir ve parametre olarak bir dizi maske sağlanabilir:
Finder::findDirectories('vendor') // tüm dizinler
->files(['*.php', '*.phpt']); // artı tüm PHP dosyaları
Statik yöntemlere bir alternatif de new Finder
adresini kullanarak bir örnek oluşturmak (bu şekilde
oluşturulan yeni nesne hiçbir şey aramaz) ve files()
ve directories()
adreslerini kullanarak ne
aranacağını belirtmektir:
(new Finder)
->directories() // tüm dizinler
->files('*.php'); // artı tüm PHP dosyaları
Joker karakter leri *
, **
adresinde kullanabilirsiniz, ?
and [...]
maske içinde. Dizinleri bile belirtebilirsiniz, örneğin src/*.php
, src
dizinindeki tüm PHP dosyalarını arayacaktır.
Simbağlar da dizin veya dosya olarak kabul edilir.
Nerede Arama Yapmalı?
Varsayılan arama dizini geçerli dizindir. Bunu in()
ve from()
yöntemlerini kullanarak
değiştirebilirsiniz. Yöntem adlarından da görebileceğiniz gibi, in()
yalnızca geçerli dizini ararken,
from()
alt dizinleri de arar (özyinelemeli olarak). Geçerli dizinde özyinelemeli arama yapmak istiyorsanız,
from('.')
adresini kullanabilirsiniz.
Bu yöntemler birden çok kez çağrılabilir veya bu yöntemlere birden çok yol diziler olarak aktarılabilir, bu durumda
dosyalar tüm dizinlerde aranacaktır. Dizinlerden biri mevcut değilse, bir Nette\UnexpectedValueException
atılır.
Finder::findFiles('*.php')
->in(['src', 'tests']) // doğrudan src/ ve tests/ içinde arama yapar
->from('vendor'); // vendor/ alt dizinlerinde de arama yapar
Göreceli yollar geçerli dizine görelidir. Elbette mutlak yollar da belirtilebilir:
Finder::findFiles('*.php')
->in('/var/www/html');
Joker karakterler *
, **
, ?
can be used in the path. For
example, you can use the path src/*/*.php
src
dizinindeki ikinci seviye dizinlerdeki tüm PHP
dosyalarını aramak için. Globstar olarak adlandırılan **
karakteri güçlü bir kozdur, çünkü alt dizinleri
de aramanıza izin verir: src
veya alt dizinlerinden herhangi birinde bulunan tests
dizinindeki tüm PHP
dosyalarını aramak için src/**/tests/*.php
kullanın.
Öte yandan, joker karakterler [...]
karakterleri yolda desteklenmez, yani örneğin in(__DIR__)
için arama yapmanız ve şans eseri []
karakterlerinin yolda görünmesi durumunda istenmeyen davranışı önlemek
için özel bir anlamı yoktur.
Dosya ve dizinleri derinlemesine ararken, önce üst dizin ve ardından içinde bulunan dosyalar döndürülür, bu
childFirst()
ile tersine çevrilebilir.
Wildcards
Maskede birkaç özel karakter kullanabilirsiniz:
*
– replaces any number of arbitrary characters (except/
)**
–/
dahil olmak üzere herhangi bir sayıda rastgele karakterin yerini alır (yani çok seviyeli olarak aranabilir)?
– replaces one arbitrary character (except/
)[a-z]
– köşeli parantez içindeki karakter listesinden bir karakteri değiştirir[!a-z]
– köşeli parantez içindeki karakter listesinin dışındaki bir karakteri değiştirir
Kullanım örnekleri:
img/?.png
–0.png
,1.png
,x.png
, vb. tek harfli adlara sahip dosyalar.logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log
– biçimindeki günlük dosyalarıYYYY-MM-DD
src/**/tests/*
–src/tests
,src/foo/tests
,src/foo/bar/tests
ve benzeri dizinlerdeki dosyalar.docs/**.md
– dizinin tüm alt dizinlerinde bulunan.md
uzantılı tüm dosyalardocs
Hariç
Dosyaları ve dizinleri aramaların dışında tutmak için exclude()
yöntemini kullanın. Dosyanın
eşleşmemesi gereken bir maske belirtirsiniz. Adında X
harfi bulunanlar dışında *.txt
dosyalarının aranmasına örnek:
Finder::findFiles('*.txt')
->exclude('*X*');
Taranan alt dizinleri atlamak için exclude()
adresini kullanın:
Finder::findFiles('*.php')
->from($dir)
->exclude('temp', '.git')
Filtreleme
Finder, sonuçları filtrelemek (yani azaltmak) için çeşitli yöntemler sunar. Bunları birleştirebilir ve tekrar tekrar çağırabilirsiniz.
Dosya boyutuna göre filtrelemek için size()
adresini kullanın. Bu şekilde, boyutları 100 ile 200 bayt
arasında olan dosyaları buluruz:
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200);
date()
yöntemi, dosyanın en son değiştirildiği tarihe göre filtreler. Değerler, geçerli tarih ve saate
göre mutlak veya göreli olabilir; örneğin, son iki hafta içinde değiştirilen dosyalar bu şekilde bulunabilir:
Finder::findFiles('*.php')
->date('>', '-2 weeks')
->from($dir)
Her iki işlev de >
, >=
, <
, <=
, =
,
!=
, <>
operatörlerini anlar.
Finder ayrıca özel işlevler kullanarak sonuçları filtrelemenize de olanak tanır. İşlev, parametre olarak bir
Nette\Utils\FileInfo
nesnesi alır ve dosyayı sonuçlara dahil etmek için true
döndürmelidir.
Örnek: Nette
dizesini içeren PHP dosyalarını arayın (büyük/küçük harfe duyarlı değil):
Finder::findFiles('*.php')
->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
Derinlik Filtreleme
Özyinelemeli arama yaparken, limitDepth()
yöntemini kullanarak maksimum tarama derinliğini ayarlayabilirsiniz.
limitDepth(1)
ayarlarsanız, yalnızca ilk alt dizinler taranır, limitDepth(0)
derinlik taramasını
devre dışı bırakır ve –1 değeri sınırı iptal eder.
Finder, tarama yaparken hangi dizine girileceğine karar vermek için kendi işlevlerini kullanmanıza izin verir. İşlev
parametre olarak bir Nette\Utils\FileInfo
nesnesi alır ve dizine girmek için true
döndürmelidir:
Finder::findFiles('*.php')
->descentFilter($file->getBasename() !== 'temp');
Sıralama
Finder ayrıca sonuçları sıralamak için çeşitli işlevler sunar.
sortByName()
yöntemi sonuçları dosya adına göre sıralar. Sıralama doğaldır, yani adlardaki sayıları
doğru bir şekilde işler ve örneğin foo1.txt
'u foo10.txt
'dan önce döndürür.
Finder ayrıca özel bir fonksiyon kullanarak sıralama yapmanıza da olanak tanır. Parametre olarak iki
Nette\Utils\FileInfo
nesnesi alır ve operatör ile karşılaştırmanın sonucunu döndürmelidir
<=>
yani -1
, 0
nebo 1
. Örneğin, dosyaları boyutlarına göre bu
şekilde sıralayabiliriz:
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
Çoklu Farklı Aramalar
Farklı konumlarda veya farklı kriterleri karşılayan birden fazla farklı dosya bulmanız gerekiyorsa, append()
yöntemini kullanın. Yöntem çağrılarını zincirleyebilmeniz için yeni bir Finder
nesnesi döndürür:
($finder = new Finder) // ilk Finder'ı $finder değişkeninde saklayın!
->files('*.php') // src/ içinde *.php dosyalarını ara
->from('src')
->append()
->files('*.md') // docs/ içinde *.md dosyalarını arayın
->from('docs')
->append()
->files('*.json'); // geçerli klasörde *.json dosyalarını arayın
Alternatif olarak, belirli bir dosyayı (veya bir dizi dosyayı) eklemek için append()
yöntemini
kullanabilirsiniz. O zaman aynı nesneyi döndürür Finder
:
$finder = Finder::findFiles('*.txt')
->append(__FILE__);
FileInfo
Nette\Utils\FileInfo, arama sonuçlarındaki bir dosya veya dizini temsil eden bir sınıftır. Dosya boyutu, son değiştirilme tarihi, adı, yolu gibi bilgileri sağlayan SplFileInfo sınıfının bir uzantısıdır.
Ayrıca, derinlemesine tarama yaparken yararlı olan göreli yolları döndürmek için yöntemler sağlar:
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
$absoluteFilePath = $file->getRealPath();
$relativeFilePath = $file->getRelativePathname();
}
Bir dosyanın içeriğini okumak ve yazmak için de yöntemleriniz vardır:
foreach ($finder as $file) {
$contents = $file->read();
// ...
$file->write($contents);
}
Sonuçları Dizi Olarak Döndürme
Örneklerde görüldüğü gibi, Finder IteratorAggregate
arayüzünü uygular, böylece sonuçlara göz atmak
için foreach
adresini kullanabilirsiniz. Sonuçlar yalnızca siz göz attıkça yüklenecek şekilde
programlanmıştır, bu nedenle çok sayıda dosyanız varsa, hepsinin okunmasını beklemez.
Ayrıca collect()
yöntemini kullanarak sonuçların Nette\Utils\FileInfo
nesnelerinden oluşan bir
dizi olarak döndürülmesini sağlayabilirsiniz. Dizi ilişkisel değil, sayısaldır.
$array = $finder->findFiles('*.php')->collect();