Nette Documentation Preview

syntax
Finder: wyszukiwanie plików
***************************

.[perex]
Potrzebujesz znaleźć pliki pasujące do określonej maski? Finder może ci pomóc. Jest to wszechstronne i szybkie narzędzie do przeglądania struktury katalogów.


Instalacja:

```shell
composer require nette/utils
```

W przykładach założono, że alias został utworzony:

```php
use Nette\Utils\Finder;
```


Korzystanie z
-------------

Najpierw zobaczmy, jak można użyć [api:Nette\Utils\Finder] do wypisania nazw plików z rozszerzeniami `.txt` i `.md` w bieżącym katalogu:

```php
foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
	echo $file;
}
```

Domyślnym katalogiem dla wyszukiwania jest katalog bieżący, ale możesz go zmienić używając metod [in() lub from() |#Kde se má hledat?].
Zmienna `$file` jest instancją klasy [FileInfo |#FileInfo] z wieloma przydatnymi metodami. Klucz `$name` zawiera ścieżkę do pliku jako ciąg znaków.


Na co zwrócić uwagę? .[#toc-co-se-ma-hledat]
--------------------------------------------

Oprócz metody `findFiles()` istnieje również `findDirectories()`, która przeszukuje tylko katalogi, oraz `find()`, która przeszukuje oba katalogi. Te metody są statyczne, więc można je wywołać bez tworzenia instancji. Parametr maski jest opcjonalny, jeśli go nie określisz, wszystko jest przeszukiwane.

```php
foreach (Finder::find() as $file) {
	echo $file; // wszystkie pliki i katalogi są teraz wymienione
}
```

Użyj metod `files()` i `directories()`, aby dodać, co jeszcze należy wyszukać. Metody te mogą być wywoływane wielokrotnie, a jako parametr można podać tablicę masek:

```php
Finder::findDirectories('vendor') // wszystkie katalogi
	->files(['*.php', '*.phpt']); // plus wszystkie pliki PHP
```

Alternatywą dla metod statycznych jest utworzenie instancji za pomocą `new Finder` (świeży obiekt utworzony w ten sposób niczego nie wyszukuje) i określenie, czego ma szukać za pomocą `files()` i `directories()`:

```php
(new Finder)
	->directories() // wszystkie katalogi
	->files('*.php'); // plus wszystkie pliki PHP
```

W masce można używać [znaków wieloznacznych |#Excluding] `*`, `**`, `?` a `[...]`. Możesz nawet określić w katalogach, na przykład `src/*.php` będzie szukać wszystkich plików PHP w katalogu `src`.

Symlinki są również uważane za katalogi lub pliki.


Gdzie szukać? .[#toc-kde-se-ma-hledat]
--------------------------------------

Domyślnym katalogiem wyszukiwania jest katalog bieżący. Możesz to zmienić używając metod `in()` i `from()` Jak widać z nazw metod, `in()` przeszukuje tylko bieżący katalog, natomiast `from()` przeszukuje jego podkatalogi (rekurencyjnie). Jeśli chcesz szukać rekurencyjnie w bieżącym katalogu, możesz użyć `from('.')`.

Możesz wywołać te metody wielokrotnie lub przekazać do nich wiele ścieżek jako tablice, wtedy pliki będą przeszukiwane we wszystkich katalogach. Jeśli jeden z katalogów nie istnieje, rzucany jest wyjątek `Nette\UnexpectedValueException`.

```php
Finder::findFiles('*.php')
	->in(['src', 'tests']) // wyszukuje bezpośrednio w src/ i tests/
	->from('vendor'); // wyszukuje również w podkatalogach vendor/
```

Ścieżki relatywne są względne w stosunku do bieżącego katalogu. Oczywiście można również określić ścieżki bezwzględne:

```php
Finder::findFiles('*.php')
	->in('/var/www/html');
```

Możesz użyć symboli wieloznacznych `*`, `**`, `?`. Můžete tak třeba pomocí cesty `src/*/*.php` w ścieżce, aby wyszukać wszystkie pliki PHP w katalogach drugiego poziomu w katalogu `src`. Symbol [wieloznaczny |#Excluding] `**`, zwany globstar, jest potężnym atutem, ponieważ pozwala na wyszukiwanie również w podkatalogach: użyj `src/**/tests/*.php`, aby wyszukać wszystkie pliki PHP w katalogu `tests` znajdujące się w `src` lub dowolnym jego podkatalogu.

Z drugiej strony, symbole wieloznaczne `[...]` znaki nie są obsługiwane w ścieżce, tzn. nie mają specjalnego znaczenia, aby uniknąć niepożądanego zachowania w przypadku, gdy użytkownik szuka `in(__DIR__)` i przypadkowo w ścieżce pojawiają się znaki `[]`.

Podczas wyszukiwania plików i katalogów w głąb, najpierw zwracany jest katalog nadrzędny, a następnie pliki w nim zawarte, co można odwrócić za pomocą `childFirst()`.


Żbiki
-----

W masce można użyć kilku znaków specjalnych:

- `*` - nahrazuje libovolný počet libovolných znaků (kromě `/`)
- `**` - zastępuje dowolną liczbę dowolnych znaków, w tym `/` (czyli może być przeszukiwany wielopoziomowo)
- `?` - nahrazuje jeden libovolný znak (kromě `/`)
- `[a-z]` - zastępuje jeden znak z listy znaków w nawiasach kwadratowych
- `[!a-z]` - zastępuje jeden znak spoza listy znaków w nawiasach kwadratowych

Przykłady zastosowania:

- `img/?.png` - pliki o jednoliterowej nazwie `0.png`, `1.png`, `x.png`, itd.
- `logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log` - pliki dziennika w formacie `YYYY-MM-DD`
- `src/**/tests/*` - pliki w katalogu `src/tests`, `src/foo/tests`, `src/foo/bar/tests` i tak dalej.
- `docs/**.md` - wszystkie pliki z rozszerzeniem `.md` we wszystkich podkatalogach katalogu `docs`


Z wyłączeniem
-------------

Użyj metody `exclude()`, aby wykluczyć pliki i katalogi z wyszukiwań. Określasz maskę, do której plik nie może pasować. Przykład wyszukiwania plików `*.txt` z wyjątkiem tych zawierających w nazwie literę `X`:

```php
Finder::findFiles('*.txt')
	->exclude('*X*');
```

Użyj `exclude()` aby pominąć przeglądane podkatalogi:

```php
Finder::findFiles('*.php')
	->from($dir)
	->exclude('temp', '.git')
```


Filtrowanie .[#toc-filtrovani]
------------------------------

Finder oferuje kilka metod filtrowania wyników (czyli ich zmniejszania). Można je łączyć i nazywać wielokrotnie.

Użyj `size()`, aby filtrować według rozmiaru pliku. W ten sposób znajdujemy pliki o rozmiarach od 100 do 200 bajtów:

```php
Finder::findFiles('*.php')
	->size('>=', 100)
	->size('<=', 200);
```

Metoda `date()` filtruje według daty ostatniej modyfikacji pliku. Wartości mogą być bezwzględne lub względne w stosunku do bieżącej daty i czasu, na przykład w ten sposób można znaleźć pliki zmienione w ciągu ostatnich dwóch tygodni:

```php
Finder::findFiles('*.php')
	->date('>', '-2 weeks')
	->from($dir)
```

Obie funkcje rozumieją operatory `>`, `>=`, `<`, `<=`, `=`, `!=`, `<>`.

Finder umożliwia również filtrowanie wyników przy użyciu funkcji niestandardowych. Funkcja otrzymuje jako parametr obiekt `Nette\Utils\FileInfo` i musi zwrócić `true`, aby włączyć plik do wyników.

Przykład: wyszukaj pliki PHP, które zawierają ciąg `Nette` (wielkość liter nie ma znaczenia):

```php
Finder::findFiles('*.php')
	->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);
```


Filtrowanie głębokości .[#toc-filtrovani-do-hloubky]
----------------------------------------------------

Podczas wyszukiwania rekurencyjnego można ustawić maksymalną głębokość indeksowania za pomocą metody `limitDepth()`. Jeśli ustawisz `limitDepth(1)`, indeksowane są tylko pierwsze podkatalogi, `limitDepth(0)` wyłącza indeksowanie głębokości, a wartość -1 anuluje limit.

Finder pozwala na wykorzystanie własnych funkcji do decydowania, do którego katalogu wejść podczas przeglądania. Funkcja otrzymuje jako parametr obiekt `Nette\Utils\FileInfo` i musi zwrócić `true`, aby wejść do katalogu:

```php
Finder::findFiles('*.php')
	->descentFilter($file->getBasename() !== 'temp');
```


Sortowanie .[#toc-razeni]
-------------------------

Finder oferuje również kilka funkcji sortowania wyników.

Metoda `sortByName()` sortuje wyniki według nazwy pliku. Sortowanie jest naturalne, tzn. poprawnie obsługuje liczby w nazwach i zwraca np. `foo1.txt` przed `foo10.txt`.

Finder umożliwia również sortowanie przy użyciu funkcji niestandardowej. Przyjmuje dwa obiekty `Nette\Utils\FileInfo` jako parametry i musi zwrócić wynik porównania za pomocą operatora `<=>`, czyli `-1`, `0` nebo `1`. Na przykład w ten sposób sortujemy pliki według wielkości:

```php
$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());
```


Wiele różnych wyszukiwań .[#toc-vice-ruznych-hledani]
-----------------------------------------------------

Jeśli musisz znaleźć wiele różnych plików w różnych lokalizacjach lub spełniających różne kryteria, użyj metody `append()`. Zwraca ona nowy obiekt `Finder`, dzięki czemu możesz łączyć wywołania metod:


```php
($finder = new Finder) // przechowuj pierwszego Findera w zmiennej $finder!
	->files('*.php') // szukaj plików *.php w src/
	->from('src')
	->append()
	->files('*.md') // w docs/ szukaj plików *.md
	->from('docs')
	->append()
	->files('*.json'); // w bieżącym folderze szukaj plików *.json
```

Alternatywnie możesz użyć metody `append()`, aby dodać określony plik (lub tablicę plików). Następnie zwraca ten sam obiekt `Finder`:

```php
$finder = Finder::findFiles('*.txt')
	->append(__FILE__);
```


FileInfo .[#toc-fileinfo]
-------------------------

[Nette\Utils\FileInfo |api:] to klasa reprezentująca plik lub katalog w wynikach wyszukiwania. Jest to rozszerzenie klasy [SplFileInfo |php:SplFileInfo], które dostarcza informacji takich jak rozmiar pliku, data ostatniej modyfikacji, nazwa, ścieżka itp.

Dodatkowo zapewnia metody zwracania ścieżek względnych, co jest przydatne podczas głębokiego przeglądania:

```php
foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
	$absoluteFilePath = $file->getRealPath();
	$relativeFilePath = $file->getRelativePathname();
}
```

Masz również metody odczytu i zapisu zawartości pliku:

```php
foreach ($finder as $file) {
    $contents = $file->read();
    // ...
    $file->write($contents);
}
```


Zwracanie wyników w postaci tablicy .[#toc-vraceni-vysledku-jako-pole]
----------------------------------------------------------------------

Jak widać w przykładach, Finder implementuje interfejs `IteratorAggregate`, więc możesz użyć `foreach` do przeglądania wyników. Jest zaprogramowany tak, że wyniki są ładowane tylko w trakcie przeglądania, więc jeśli masz dużą liczbę plików, nie czeka na odczytanie ich wszystkich.

Możesz również zlecić zwrócenie wyników w postaci tablicy obiektów `Nette\Utils\FileInfo`, używając metody `collect()` Tablica nie jest asocjacyjna, lecz numeryczna.

```php
$array = $finder->findFiles('*.php')->collect();
```

Finder: wyszukiwanie plików

Potrzebujesz znaleźć pliki pasujące do określonej maski? Finder może ci pomóc. Jest to wszechstronne i szybkie narzędzie do przeglądania struktury katalogów.

Instalacja:

composer require nette/utils

W przykładach założono, że alias został utworzony:

use Nette\Utils\Finder;

Korzystanie z

Najpierw zobaczmy, jak można użyć Nette\Utils\Finder do wypisania nazw plików z rozszerzeniami .txt i .md w bieżącym katalogu:

foreach (Finder::findFiles(['*.txt', '*.md']) as $name => $file) {
	echo $file;
}

Domyślnym katalogiem dla wyszukiwania jest katalog bieżący, ale możesz go zmienić używając metod in() lub from(). Zmienna $file jest instancją klasy FileInfo z wieloma przydatnymi metodami. Klucz $name zawiera ścieżkę do pliku jako ciąg znaków.

Na co zwrócić uwagę?

Oprócz metody findFiles() istnieje również findDirectories(), która przeszukuje tylko katalogi, oraz find(), która przeszukuje oba katalogi. Te metody są statyczne, więc można je wywołać bez tworzenia instancji. Parametr maski jest opcjonalny, jeśli go nie określisz, wszystko jest przeszukiwane.

foreach (Finder::find() as $file) {
	echo $file; // wszystkie pliki i katalogi są teraz wymienione
}

Użyj metod files() i directories(), aby dodać, co jeszcze należy wyszukać. Metody te mogą być wywoływane wielokrotnie, a jako parametr można podać tablicę masek:

Finder::findDirectories('vendor') // wszystkie katalogi
	->files(['*.php', '*.phpt']); // plus wszystkie pliki PHP

Alternatywą dla metod statycznych jest utworzenie instancji za pomocą new Finder (świeży obiekt utworzony w ten sposób niczego nie wyszukuje) i określenie, czego ma szukać za pomocą files() i directories():

(new Finder)
	->directories() // wszystkie katalogi
	->files('*.php'); // plus wszystkie pliki PHP

W masce można używać znaków wieloznacznych *, **, ? a [...]. Możesz nawet określić w katalogach, na przykład src/*.php będzie szukać wszystkich plików PHP w katalogu src.

Symlinki są również uważane za katalogi lub pliki.

Gdzie szukać?

Domyślnym katalogiem wyszukiwania jest katalog bieżący. Możesz to zmienić używając metod in() i from() Jak widać z nazw metod, in() przeszukuje tylko bieżący katalog, natomiast from() przeszukuje jego podkatalogi (rekurencyjnie). Jeśli chcesz szukać rekurencyjnie w bieżącym katalogu, możesz użyć from('.').

Możesz wywołać te metody wielokrotnie lub przekazać do nich wiele ścieżek jako tablice, wtedy pliki będą przeszukiwane we wszystkich katalogach. Jeśli jeden z katalogów nie istnieje, rzucany jest wyjątek Nette\UnexpectedValueException.

Finder::findFiles('*.php')
	->in(['src', 'tests']) // wyszukuje bezpośrednio w src/ i tests/
	->from('vendor'); // wyszukuje również w podkatalogach vendor/

Ścieżki relatywne są względne w stosunku do bieżącego katalogu. Oczywiście można również określić ścieżki bezwzględne:

Finder::findFiles('*.php')
	->in('/var/www/html');

Możesz użyć symboli wieloznacznych *, **, ?. Můžete tak třeba pomocí cesty src/*/*.php w ścieżce, aby wyszukać wszystkie pliki PHP w katalogach drugiego poziomu w katalogu src. Symbol wieloznaczny **, zwany globstar, jest potężnym atutem, ponieważ pozwala na wyszukiwanie również w podkatalogach: użyj src/**/tests/*.php, aby wyszukać wszystkie pliki PHP w katalogu tests znajdujące się w src lub dowolnym jego podkatalogu.

Z drugiej strony, symbole wieloznaczne [...] znaki nie są obsługiwane w ścieżce, tzn. nie mają specjalnego znaczenia, aby uniknąć niepożądanego zachowania w przypadku, gdy użytkownik szuka in(__DIR__) i przypadkowo w ścieżce pojawiają się znaki [].

Podczas wyszukiwania plików i katalogów w głąb, najpierw zwracany jest katalog nadrzędny, a następnie pliki w nim zawarte, co można odwrócić za pomocą childFirst().

Żbiki

W masce można użyć kilku znaków specjalnych:

  • * – nahrazuje libovolný počet libovolných znaků (kromě /)
  • ** – zastępuje dowolną liczbę dowolnych znaków, w tym / (czyli może być przeszukiwany wielopoziomowo)
  • ? – nahrazuje jeden libovolný znak (kromě /)
  • [a-z] – zastępuje jeden znak z listy znaków w nawiasach kwadratowych
  • [!a-z] – zastępuje jeden znak spoza listy znaków w nawiasach kwadratowych

Przykłady zastosowania:

  • img/?.png – pliki o jednoliterowej nazwie 0.png, 1.png, x.png, itd.
  • logs/[0-9][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9].log – pliki dziennika w formacie YYYY-MM-DD
  • src/**/tests/* – pliki w katalogu src/tests, src/foo/tests, src/foo/bar/tests i tak dalej.
  • docs/**.md – wszystkie pliki z rozszerzeniem .md we wszystkich podkatalogach katalogu docs

Z wyłączeniem

Użyj metody exclude(), aby wykluczyć pliki i katalogi z wyszukiwań. Określasz maskę, do której plik nie może pasować. Przykład wyszukiwania plików *.txt z wyjątkiem tych zawierających w nazwie literę X:

Finder::findFiles('*.txt')
	->exclude('*X*');

Użyj exclude() aby pominąć przeglądane podkatalogi:

Finder::findFiles('*.php')
	->from($dir)
	->exclude('temp', '.git')

Filtrowanie

Finder oferuje kilka metod filtrowania wyników (czyli ich zmniejszania). Można je łączyć i nazywać wielokrotnie.

Użyj size(), aby filtrować według rozmiaru pliku. W ten sposób znajdujemy pliki o rozmiarach od 100 do 200 bajtów:

Finder::findFiles('*.php')
	->size('>=', 100)
	->size('<=', 200);

Metoda date() filtruje według daty ostatniej modyfikacji pliku. Wartości mogą być bezwzględne lub względne w stosunku do bieżącej daty i czasu, na przykład w ten sposób można znaleźć pliki zmienione w ciągu ostatnich dwóch tygodni:

Finder::findFiles('*.php')
	->date('>', '-2 weeks')
	->from($dir)

Obie funkcje rozumieją operatory >, >=, <, <=, =, !=, <>.

Finder umożliwia również filtrowanie wyników przy użyciu funkcji niestandardowych. Funkcja otrzymuje jako parametr obiekt Nette\Utils\FileInfo i musi zwrócić true, aby włączyć plik do wyników.

Przykład: wyszukaj pliki PHP, które zawierają ciąg Nette (wielkość liter nie ma znaczenia):

Finder::findFiles('*.php')
	->filter(fn($file) => strcasecmp($file->read(), 'Nette') === 0);

Filtrowanie głębokości

Podczas wyszukiwania rekurencyjnego można ustawić maksymalną głębokość indeksowania za pomocą metody limitDepth(). Jeśli ustawisz limitDepth(1), indeksowane są tylko pierwsze podkatalogi, limitDepth(0) wyłącza indeksowanie głębokości, a wartość –1 anuluje limit.

Finder pozwala na wykorzystanie własnych funkcji do decydowania, do którego katalogu wejść podczas przeglądania. Funkcja otrzymuje jako parametr obiekt Nette\Utils\FileInfo i musi zwrócić true, aby wejść do katalogu:

Finder::findFiles('*.php')
	->descentFilter($file->getBasename() !== 'temp');

Sortowanie

Finder oferuje również kilka funkcji sortowania wyników.

Metoda sortByName() sortuje wyniki według nazwy pliku. Sortowanie jest naturalne, tzn. poprawnie obsługuje liczby w nazwach i zwraca np. foo1.txt przed foo10.txt.

Finder umożliwia również sortowanie przy użyciu funkcji niestandardowej. Przyjmuje dwa obiekty Nette\Utils\FileInfo jako parametry i musi zwrócić wynik porównania za pomocą operatora <=>, czyli -1, 0 nebo 1. Na przykład w ten sposób sortujemy pliki według wielkości:

$finder->sortBy(fn($a, $b) => $a->getSize() <=> $b->getSize());

Wiele różnych wyszukiwań

Jeśli musisz znaleźć wiele różnych plików w różnych lokalizacjach lub spełniających różne kryteria, użyj metody append(). Zwraca ona nowy obiekt Finder, dzięki czemu możesz łączyć wywołania metod:

($finder = new Finder) // przechowuj pierwszego Findera w zmiennej $finder!
	->files('*.php') // szukaj plików *.php w src/
	->from('src')
	->append()
	->files('*.md') // w docs/ szukaj plików *.md
	->from('docs')
	->append()
	->files('*.json'); // w bieżącym folderze szukaj plików *.json

Alternatywnie możesz użyć metody append(), aby dodać określony plik (lub tablicę plików). Następnie zwraca ten sam obiekt Finder:

$finder = Finder::findFiles('*.txt')
	->append(__FILE__);

FileInfo

Nette\Utils\FileInfo to klasa reprezentująca plik lub katalog w wynikach wyszukiwania. Jest to rozszerzenie klasy SplFileInfo, które dostarcza informacji takich jak rozmiar pliku, data ostatniej modyfikacji, nazwa, ścieżka itp.

Dodatkowo zapewnia metody zwracania ścieżek względnych, co jest przydatne podczas głębokiego przeglądania:

foreach (Finder::findFiles('*.jpg')->from('.') as $file) {
	$absoluteFilePath = $file->getRealPath();
	$relativeFilePath = $file->getRelativePathname();
}

Masz również metody odczytu i zapisu zawartości pliku:

foreach ($finder as $file) {
    $contents = $file->read();
    // ...
    $file->write($contents);
}

Zwracanie wyników w postaci tablicy

Jak widać w przykładach, Finder implementuje interfejs IteratorAggregate, więc możesz użyć foreach do przeglądania wyników. Jest zaprogramowany tak, że wyniki są ładowane tylko w trakcie przeglądania, więc jeśli masz dużą liczbę plików, nie czeka na odczytanie ich wszystkich.

Możesz również zlecić zwrócenie wyników w postaci tablicy obiektów Nette\Utils\FileInfo, używając metody collect() Tablica nie jest asocjacyjna, lecz numeryczna.

$array = $finder->findFiles('*.php')->collect();