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
βρίσκεται η διαδρομή προς το αρχείο ως string.
Τι να αναζητήσετε;
Εκτός από τη μέθοδο findFiles()
, υπάρχει επίσης η findDirectories()
,
που αναζητά μόνο καταλόγους, και η find()
, που αναζητά και τα δύο.
Αυτές οι μέθοδοι είναι στατικές, έτσι μπορούν να κληθούν χωρίς τη
δημιουργία στιγμιότυπου. Η παράμετρος με τη μάσκα είναι προαιρετική,
αν δεν την καθορίσετε, θα αναζητηθούν όλα.
foreach (Finder::find() as $file) {
echo $file; // nyní se vypíší všechny soubory i adresáře - τώρα θα εκτυπωθούν όλα τα αρχεία και οι κατάλογοι
}
Με τις μεθόδους files()
και directories()
μπορείτε να
συμπληρώσετε τι άλλο να αναζητήσετε. Οι μέθοδοι μπορούν να κληθούν
επανειλημμένα και ως παράμετρος μπορεί να δοθεί και ένας πίνακας
μασκών:
Finder::findDirectories('vendor') // všechny adresáře - όλοι οι κατάλογοι
->files(['*.php', '*.phpt']); // plus všechny PHP soubory - συν όλα τα αρχεία PHP
Μια εναλλακτική λύση στις στατικές μεθόδους είναι η δημιουργία ενός
στιγμιότυπου με new Finder
(ένα τέτοιο νεοδημιουργημένο αντικείμενο
δεν αναζητά τίποτα) και ο καθορισμός του τι να αναζητήσετε
χρησιμοποιώντας τις files()
και directories()
:
(new Finder)
->directories() // všechny adresáře - όλοι οι κατάλογοι
->files('*.php'); // plus všechny PHP soubory - συν όλα τα αρχεία PHP
Στη μάσκα μπορείτε να χρησιμοποιήσετε χαρακτήρες
μπαλαντέρ *
, **
, ?
και [...]
. Μπορείτε ακόμη να
καθορίσετε και σε καταλόγους, για παράδειγμα το src/*.php
αναζητά
όλα τα αρχεία PHP στον κατάλογο src
.
Οι συμβολικοί σύνδεσμοι θεωρούνται επίσης κατάλογοι ή αρχεία.
Πού να ψάξετε;
Ο προεπιλεγμένος κατάλογος για αναζήτηση είναι ο τρέχων κατάλογος.
Θα τον αλλάξετε χρησιμοποιώντας τις μεθόδους in()
και from()
.
Όπως είναι εμφανές από τα ονόματα των μεθόδων, η in()
αναζητά μόνο
στον δεδομένο κατάλογο, ενώ η from()
αναζητά και στους
υποκαταλόγους του (αναδρομικά). Αν θέλετε να αναζητήσετε αναδρομικά
στον τρέχοντα κατάλογο, μπορείτε να χρησιμοποιήσετε το from('.')
.
Αυτές οι μέθοδοι μπορούν να κληθούν πολλές φορές ή να τους περάσετε
πολλαπλές διαδρομές ως πίνακα, τα αρχεία θα αναζητηθούν τότε σε όλους
τους καταλόγους. Αν κάποιος από τους καταλόγους δεν υπάρχει, θα ριχτεί
μια εξαίρεση Nette\UnexpectedValueException
.
Finder::findFiles('*.php')
->in(['src', 'tests']) // hledá přímo v src/ a tests/ - αναζητά απευθείας στο src/ και tests/
->from('vendor'); // hledá i v podadresářích vendor/ - αναζητά και στους υποκαταλόγους vendor/
Οι σχετικές διαδρομές είναι σχετικές με τον τρέχοντα κατάλογο. Μπορούν φυσικά να δοθούν και απόλυτες διαδρομές:
Finder::findFiles('*.php')
->in('/var/www/html');
Στη διαδρομή είναι δυνατό να χρησιμοποιηθούν χαρακτήρες μπαλαντέρ χαρακτήρες μπαλαντέρ *
, **
, ?
.
Μπορείτε έτσι, για παράδειγμα, χρησιμοποιώντας τη διαδρομή
src/*/*.php
να αναζητήσετε όλα τα αρχεία PHP σε καταλόγους δεύτερου
επιπέδου στον κατάλογο src
. Ο χαρακτήρας **
που ονομάζεται
globstar είναι ένα ισχυρό ατού, επειδή επιτρέπει την αναζήτηση και σε
υποκαταλόγους: χρησιμοποιώντας το src/**/tests/*.php
αναζητάτε όλα τα
αρχεία PHP στον κατάλογο tests
που βρίσκεται στο src
ή σε
οποιονδήποτε υποκατάλογό του.
Αντίθετα, οι χαρακτήρες μπαλαντέρ [...]
στη διαδρομή δεν
υποστηρίζονται, δηλαδή δεν έχουν ειδική σημασία, για να αποφευχθεί η
ανεπιθύμητη συμπεριφορά σε περίπτωση που ψάχνετε για παράδειγμα
in(__DIR__)
και τυχαία στη διαδρομή υπάρχουν χαρακτήρες []
.
Κατά την αναζήτηση αρχείων και καταλόγων σε βάθος, επιστρέφεται
πρώτα ο γονικός κατάλογος και μόνο μετά τα αρχεία που περιέχονται σε
αυτόν, το οποίο μπορεί να αντιστραφεί χρησιμοποιώντας το
childFirst()
.
Χαρακτήρες Μπαλαντέρ
Στη μάσκα μπορείτε να χρησιμοποιήσετε αρκετούς ειδικούς χαρακτήρες:
*
– αντικαθιστά οποιονδήποτε αριθμό οποιωνδήποτε χαρακτήρων (εκτός από/
)**
– αντικαθιστά οποιονδήποτε αριθμό οποιωνδήποτε χαρακτήρων συμπεριλαμβανομένου του/
(δηλ. μπορεί να γίνει αναζήτηση σε πολλαπλά επίπεδα)?
– αντικαθιστά έναν οποιονδήποτε χαρακτήρα (εκτός από/
)[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 byte:
Finder::findFiles('*.php')
->size('>=', 100)
->size('<=', 200);
Η μέθοδος date()
φιλτράρει με βάση την ημερομηνία τελευταίας
τροποποίησης του αρχείου. Οι τιμές μπορεί να είναι απόλυτες ή σχετικές
με την τρέχουσα ημερομηνία και ώρα, για παράδειγμα, έτσι βρίσκουμε
αρχεία που τροποποιήθηκαν τις τελευταίες δύο εβδομάδες:
Finder::findFiles('*.php')
->date('>', '-2 weeks')
->from($dir)
Και οι δύο συναρτήσεις κατανοούν τους τελεστές >
, >=
,
<
, <=
, =
, !=
, <>
.
Ο Finder επιτρέπει επίσης το φιλτράρισμα των αποτελεσμάτων με
προσαρμοσμένες συναρτήσεις. Η συνάρτηση λαμβάνει ως παράμετρο ένα
αντικείμενο Nette\Utils\FileInfo
και πρέπει να επιστρέψει true
, για
να συμπεριληφθεί το αρχείο στα αποτελέσματα.
Παράδειγμα: αναζήτηση αρχείων PHP που περιέχουν το string 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
ή 1
. Για παράδειγμα, έτσι
ταξινομούμε τα αρχεία κατά μέγεθος:
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
Πολλαπλές διαφορετικές αναζητήσεις
Αν χρειάζεστε να βρείτε περισσότερα διαφορετικά αρχεία σε
διαφορετικές τοποθεσίες ή που πληρούν άλλα κριτήρια, χρησιμοποιήστε
τη μέθοδο append()
. Επιστρέφει ένα νέο αντικείμενο Finder
, οπότε
είναι δυνατή η αλυσιδωτή κλήση μεθόδων:
($finder = new Finder) // do proměnné $finder si uložíme první Finder! - στη μεταβλητή $finder αποθηκεύουμε τον πρώτο Finder!
->files('*.php') // v src/ hledáme soubory *.php - στο src/ αναζητούμε αρχεία *.php
->from('src')
->append()
->files('*.md') // v docs/ hledáme soubory *.md - στο docs/ αναζητούμε αρχεία *.md
->from('docs')
->append()
->files('*.json'); // v aktuální složce hledáme soubory *.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 υλοποιεί το interface
IteratorAggregate
, έτσι μπορείτε να χρησιμοποιήσετε το foreach
για
να διασχίσετε τα αποτελέσματα. Είναι προγραμματισμένος έτσι ώστε τα
αποτελέσματα να φορτώνονται μόνο κατά τη διάρκεια της διάσχισης, οπότε
αν έχετε μεγάλο αριθμό αρχείων, δεν περιμένει μέχρι να
διαβαστούν όλα.
Μπορείτε επίσης να λάβετε τα αποτελέσματα ως πίνακα αντικειμένων
Nette\Utils\FileInfo
, και αυτό με τη μέθοδο collect()
. Ο πίνακας δεν
είναι συσχετιστικός, αλλά αριθμητικός.
$array = $finder->findFiles('*.php')->collect();