Finder: Αναζήτηση αρχείων
Πρέπει να βρείτε αρχεία που ταιριάζουν με μια συγκεκριμένη μάσκα; Το Finder μπορεί να σας βοηθήσει. Είναι ένα ευέλικτο και γρήγορο εργαλείο για την περιήγηση στη δομή των καταλόγων.
Εγκατάσταση:
composer require nette/utils
Τα παραδείγματα υποθέτουν ότι έχει δημιουργηθεί ένα ψευδώνυμο:
use Nette\Utils\Finder;
Χρήση του
Αρχικά, ας δούμε πώς μπορείτε να χρησιμοποιήσετε το Nette\Utils\Finder για να εμφανίσετε τα
ονόματα αρχείων με τις επεκτάσεις .txt
και .md
στον τρέχοντα
κατάλογο:
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
echo $file;
}
Ο προεπιλεγμένος κατάλογος για την αναζήτηση είναι ο τρέχων
κατάλογος, αλλά μπορείτε να τον αλλάξετε χρησιμοποιώντας τις μεθόδους
in() ή from(). Η μεταβλητή $file
είναι μια περίπτωση
της κλάσης FileInfo με πολλές χρήσιμες μεθόδους. Το κλειδί
$name
περιέχει τη διαδρομή προς το αρχείο ως συμβολοσειρά.
Τι να αναζητήσετε;
Εκτός από τη μέθοδο findFiles()
, υπάρχει επίσης η μέθοδος
findDirectories()
, η οποία αναζητά μόνο καταλόγους, και η μέθοδος
find()
, η οποία αναζητά και τα δύο. Αυτές οι μέθοδοι είναι στατικές,
οπότε μπορούν να κληθούν χωρίς να δημιουργηθεί μια περίπτωση. Η
παράμετρος mask είναι προαιρετική, αν δεν την καθορίσετε, αναζητούνται
τα πάντα.
foreach (Finder::find() as $file) {
echo $file; // τώρα εμφανίζονται όλα τα αρχεία και οι κατάλογοι
}
Χρησιμοποιήστε τις μεθόδους files()
και directories()
για να
προσθέσετε τι άλλο θα αναζητήσετε. Οι μέθοδοι μπορούν να κληθούν
επανειλημμένα και ένας πίνακας από μάσκες μπορεί να δοθεί ως
παράμετρος:
Finder::findDirectories('vendor') // όλοι οι κατάλογοι
->files(['*.php', '*.phpt']); // καθώς και όλα τα αρχεία PHP
Μια εναλλακτική λύση αντί των στατικών μεθόδων είναι να
δημιουργήσετε μια περίπτωση χρησιμοποιώντας το new Finder
(το
φρέσκο αντικείμενο που δημιουργείται με αυτόν τον τρόπο δεν αναζητά
τίποτα) και να καθορίσετε τι θα αναζητήσετε χρησιμοποιώντας τις
files()
και directories()
:
(new Finder)
->directories() // όλοι οι κατάλογοι
->files('*.php'); // καθώς και όλα τα αρχεία PHP
Μπορείτε να χρησιμοποιήσετε μπαλαντέρ *
,
**
, ?
and [...]
στη μάσκα. Μπορείτε ακόμη και να
καθορίσετε σε καταλόγους, για παράδειγμα, το src/*.php
θα αναζητήσει
όλα τα αρχεία PHP στον κατάλογο src
.
Οι συμβολικοί σύνδεσμοι θεωρούνται επίσης κατάλογοι ή αρχεία.
Πού να ψάξετε;
Ο προεπιλεγμένος κατάλογος αναζήτησης είναι ο τρέχων κατάλογος.
Μπορείτε να το αλλάξετε αυτό χρησιμοποιώντας τις μεθόδους in()
και from()
. Όπως μπορείτε να δείτε από τα ονόματα των μεθόδων, η
in()
αναζητά μόνο τον τρέχοντα κατάλογο, ενώ η from()
αναζητά
και τους υποκαταλόγους του (αναδρομικά). Αν θέλετε να κάνετε αναδρομική
αναζήτηση στον τρέχοντα κατάλογο, μπορείτε να χρησιμοποιήσετε τη
μέθοδο from('.')
.
Αυτές οι μέθοδοι μπορούν να κληθούν πολλές φορές ή μπορείτε να τους
περάσετε πολλαπλές διαδρομές ως πίνακες, τότε τα αρχεία θα αναζητηθούν
σε όλους τους καταλόγους. Εάν ένας από τους καταλόγους δεν υπάρχει, θα
εκπέμπεται ένα Nette\UnexpectedValueException
.
Finder::findFiles('*.php')
->in(['src', 'tests']) // αναζητά απευθείας στα src/ και tests/
->from('vendor'); // αναζητά επίσης στους υποκαταλόγους vendor/
Οι σχετικές διαδρομές είναι σχετικές με τον τρέχοντα κατάλογο. Φυσικά, μπορούν να καθοριστούν και απόλυτες διαδρομές:
Finder::findFiles('*.php')
->in('/var/www/html');
Wildcards wildcards *
, **
, ?
can be used in the path. For
example, you can use the path src/*/*.php
για την αναζήτηση όλων των αρχείων PHP
στους καταλόγους δεύτερου επιπέδου στον κατάλογο src
. Ο
χαρακτήρας **
, που ονομάζεται globstar, είναι ένα ισχυρό ατού γιατί
σας επιτρέπει να αναζητήσετε και υποκαταλόγους: χρησιμοποιήστε το
src/**/tests/*.php
για να αναζητήσετε όλα τα αρχεία PHP στον κατάλογο
tests
που βρίσκονται στον κατάλογο src
ή σε οποιονδήποτε από
τους υποκαταλόγους του.
Από την άλλη πλευρά, οι μπαλαντέρ [...]
χαρακτήρες δεν
υποστηρίζονται στη διαδρομή, δηλαδή δεν έχουν ιδιαίτερη σημασία για να
αποφύγετε ανεπιθύμητη συμπεριφορά σε περίπτωση που αναζητήσετε για
παράδειγμα in(__DIR__)
και τυχαία εμφανιστούν στη διαδρομή
χαρακτήρες []
.
Κατά την αναζήτηση αρχείων και καταλόγων σε βάθος, επιστρέφεται
πρώτα ο γονικός κατάλογος και στη συνέχεια τα αρχεία που περιέχονται
σε αυτόν, κάτι που μπορεί να αντιστραφεί με το childFirst()
.
Άγριοι χαρακτήρες
Μπορείτε να χρησιμοποιήσετε διάφορους ειδικούς χαρακτήρες στη μάσκα:
*
– replaces any number of arbitrary characters (except/
)**
– αντικαθιστά οποιονδήποτε αριθμό αυθαίρετων χαρακτήρων, συμπεριλαμβανομένου του/
(δηλ. μπορεί να γίνει αναζήτηση σε πολλαπλά επίπεδα)?
– replaces one arbitrary character (except/
)[a-z]
– αντικαθιστά έναν χαρακτήρα από τη λίστα χαρακτήρων σε αγκύλες[!a-z]
– αντικαθιστά έναν χαρακτήρα εκτός της λίστας χαρακτήρων σε αγκύλες
Παραδείγματα χρήσης:
img/?.png
– αρχεία με το όνομα ενός γράμματος0.png
,1.png
,x.png
, κ.λπ.logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log
– αρχεία καταγραφής με τη μορφήYYYY-MM-DD
src/**/tests/*
– αρχεία στον κατάλογοsrc/tests
,src/foo/tests
,src/foo/bar/tests
κ.ο.κ.docs/**.md
– όλα τα αρχεία με την επέκταση.md
σε όλους τους υποκαταλόγους του καταλόγουdocs
Εξαιρώντας το
Χρησιμοποιήστε τη μέθοδο exclude()
για να αποκλείσετε αρχεία και
καταλόγους από τις αναζητήσεις. Καθορίζετε μια μάσκα με την οποία το
αρχείο δεν πρέπει να ταιριάζει. Παράδειγμα αναζήτησης αρχείων
*.txt
εκτός από εκείνα που περιέχουν το γράμμα X
στο όνομα:
Finder::findFiles('*.txt')
->exclude('*X*');
Χρησιμοποιήστε το exclude()
για να παραλείψετε τους
αναζητούμενους υποκαταλόγους:
Finder::findFiles('*.php')
->from($dir)
->exclude('temp', '.git')
Φιλτράρισμα
Το Finder προσφέρει διάφορες μεθόδους για το φιλτράρισμα των αποτελεσμάτων (δηλαδή τη μείωσή τους). Μπορείτε να τις συνδυάσετε και να τις καλέσετε επανειλημμένα.
Χρησιμοποιήστε το size()
για να φιλτράρετε με βάση το μέγεθος του
αρχείου. Με αυτόν τον τρόπο, βρίσκουμε αρχεία με μέγεθος μεταξύ 100 και
200 bytes:
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200);
Η μέθοδος date()
φιλτράρει με βάση την ημερομηνία τελευταίας
τροποποίησης του αρχείου. Οι τιμές μπορούν να είναι απόλυτες ή
σχετικές με την τρέχουσα ημερομηνία και ώρα, για παράδειγμα, με αυτόν
τον τρόπο μπορείτε να βρείτε αρχεία που άλλαξαν τις τελευταίες δύο
εβδομάδες:
Finder::findFiles('*.php')
->date('>', '-2 weeks')
->from($dir)
Και οι δύο συναρτήσεις κατανοούν τους τελεστές >
, >=
,
<
, <=
, =
, !=
, <>
.
Το Finder σας επιτρέπει επίσης να φιλτράρετε τα αποτελέσματα
χρησιμοποιώντας προσαρμοσμένες συναρτήσεις. Η συνάρτηση λαμβάνει ένα
αντικείμενο Nette\Utils\FileInfo
ως παράμετρο και πρέπει να επιστρέψει
το true
για να συμπεριλάβει το αρχείο στα αποτελέσματα.
Παράδειγμα: Αναζήτηση για αρχεία PHP που περιέχουν τη συμβολοσειρά
Nette
(χωρίς να λαμβάνεται υπόψη η πεζότητα):
Finder::findFiles('*.php')
->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
Φιλτράρισμα βάθους
Κατά την αναδρομική αναζήτηση, μπορείτε να ορίσετε το μέγιστο βάθος
ανίχνευσης χρησιμοποιώντας τη μέθοδο limitDepth()
. Αν ορίσετε
limitDepth(1)
, ανιχνεύονται μόνο οι πρώτοι υποκατάλογοι,
limitDepth(0)
απενεργοποιεί την ανίχνευση βάθους και η τιμή –1
ακυρώνει το όριο.
Το Finder σας επιτρέπει να χρησιμοποιήσετε τις δικές του λειτουργίες
για να αποφασίσετε σε ποιον κατάλογο θα εισέλθετε κατά την περιήγηση. Η
συνάρτηση λαμβάνει ένα αντικείμενο Nette\Utils\FileInfo
ως παράμετρο και
πρέπει να επιστρέψει το true
για να εισέλθει στον κατάλογο:
Finder::findFiles('*.php')
->descentFilter($file->getBasename() !== 'temp');
Ταξινόμηση
Το Finder προσφέρει επίσης διάφορες λειτουργίες για την ταξινόμηση των αποτελεσμάτων.
Η μέθοδος sortByName()
ταξινομεί τα αποτελέσματα με βάση το όνομα
του αρχείου. Η ταξινόμηση είναι φυσική, δηλαδή χειρίζεται σωστά τους
αριθμούς στα ονόματα και επιστρέφει π.χ. foo1.txt
πριν από το
foo10.txt
.
Το Finder σας επιτρέπει επίσης να ταξινομήσετε χρησιμοποιώντας μια
προσαρμοσμένη συνάρτηση. Λαμβάνει δύο αντικείμενα Nette\Utils\FileInfo
ως παραμέτρους και πρέπει να επιστρέφει το αποτέλεσμα της σύγκρισης με
τον τελεστή <=>
, π.χ. -1
, 0
nebo 1
. Για
παράδειγμα, με αυτόν τον τρόπο ταξινομούμε τα αρχεία με βάση το
μέγεθος:
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
Πολλαπλές διαφορετικές αναζητήσεις
Εάν πρέπει να βρείτε πολλαπλά διαφορετικά αρχεία σε διαφορετικές
τοποθεσίες ή που πληρούν διαφορετικά κριτήρια, χρησιμοποιήστε τη
μέθοδο append()
. Επιστρέφει ένα νέο αντικείμενο Finder
, ώστε να
μπορείτε να κάνετε αλυσιδωτές κλήσεις μεθόδων:
($finder = new Finder) // αποθηκεύστε το πρώτο Finder στη μεταβλητή $finder!
->files('*.php') // αναζήτηση για αρχεία *.php στο src/
->from('src')
->append()
->files('*.md') // στο docs/ αναζητήστε αρχεία *.md
->from('docs')
->append()
->files('*.json'); // στον τρέχοντα φάκελο αναζητήστε αρχεία *.json
Εναλλακτικά, μπορείτε να χρησιμοποιήσετε τη μέθοδο append()
για
να προσθέσετε ένα συγκεκριμένο αρχείο (ή έναν πίνακα αρχείων). Τότε
επιστρέφει το ίδιο αντικείμενο Finder
:
$finder = Finder::findFiles('*.txt')
->append(__FILE__);
FileInfo
Η Nette\Utils\FileInfo είναι μια κλάση που αντιπροσωπεύει ένα αρχείο ή έναν κατάλογο στα αποτελέσματα αναζήτησης. Είναι μια επέκταση της κλάσης SplFileInfo που παρέχει πληροφορίες όπως το μέγεθος του αρχείου, την ημερομηνία τελευταίας τροποποίησης, το όνομα, τη διαδρομή κ.λπ.
Επιπλέον, παρέχει μεθόδους για την επιστροφή σχετικών διαδρομών, πράγμα που είναι χρήσιμο κατά την αναζήτηση σε βάθος:
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
$absoluteFilePath = $file->getRealPath();
$relativeFilePath = $file->getRelativePathname();
}
Έχετε επίσης μεθόδους για την ανάγνωση και την εγγραφή των περιεχομένων ενός αρχείου:
foreach ($finder as $file) {
$contents = $file->read();
// ...
$file->write($contents);
}
Επιστροφή αποτελεσμάτων ως συστοιχία
Όπως είδαμε στα παραδείγματα, το Finder υλοποιεί τη διεπαφή
IteratorAggregate
, οπότε μπορείτε να χρησιμοποιήσετε το foreach
για
να περιηγηθείτε στα αποτελέσματα. Είναι προγραμματισμένο έτσι ώστε τα
αποτελέσματα να φορτώνονται μόνο κατά την περιήγησή σας, οπότε αν
έχετε μεγάλο αριθμό αρχείων, δεν περιμένει να διαβαστούν όλα.
Μπορείτε επίσης να επιστρέψετε τα αποτελέσματα ως πίνακα
αντικειμένων Nette\Utils\FileInfo
, χρησιμοποιώντας τη μέθοδο
collect()
. Ο πίνακας δεν είναι συσχετιστικός, αλλά αριθμητικός.
$array = $finder->findFiles('*.php')->collect();