Aby pobrać listę plików o wybranym rozszerzeniu z danego katalogu najprościej jest użyć funkcji [glob](http://pl.php.net/manual/en/function.glob.php)
glob("*.jpg"); |
Jeśli chcemy pobrać pliki z danego katalogu i jego podkatalogów trzeba sobie dopisać wersję rekurencyjną funkcji glob:
function glob_recur($pattern='*', $flags = 0, $path = '') { $paths = glob($path.'*', GLOB_MARK|GLOB_ONLYDIR|GLOB_NOSORT); $files = glob($path.$pattern, $flags); foreach ($paths as $path) { $files = array_merge($files, glob_recur($pattern, $flags, $path)); } return $files; } |
Funkcja glob umożliwia użycie tzw. wilkardów czyli w najprostszym ujęciu pytanik „?” zastępuje dowolny znak, a gwiazdka „*” dowolny ciąg znaków. Wilkardy to nie wyrażenia regularne i szybko odczujemy różnicę choćby w przypadku, kiedy chcielibyśmy pobrać pliki o rozszerzeniu np. css i js. W takiej sytuacji musielibyśmy dwa razy wywołać funkcję glob. Do dyspozycji mamy jednak funkcję [scandir](http://pl.php.net/manual/en/function.scandir.php), która ułatwia listowanie katalogu.
function get_files_from_dir($path, $extensions = array()) { $entries = scandir($path.'/'); $files = array(); foreach($entries as $entry) { if ($entry == '.' || $entry == '..') continue; $_path = $path.'/'.$entry; if(is_file($_path)) { if (!empty($extensions)) { $ext = pathinfo($filename, PATHINFO_EXTENSION); if (!in_array($ext, $extensions)) continue; } $files[] = $_path; } } return $files; } |
Scandir wybierze wszystkie pliki i katalogi z zadanej lokalizacji. Odróżnienie plików od katalogów to prosty tekst przy użyciu funkcji is_file lub is_dir z kolei wydobycie rozszerzenia z pliku można przeprowadzić na kilka sposobów:
$ext = pathinfo($filename, PATHINFO_EXTENSION); // lub $ext = preg_replace('/.*\.([\d\w]{2,5})/i', '$1', $filename); //zakładam, że rozszerzenie ma od 2 do 5 znaków // lub $ext = substr($filename , strrpos($filename , '.') +1); |
Modyfikacja funkcji get_files_from_dir tak aby działała rekurencyjnie wymaga jedynie niewielkiej zmiany:
function get_files_from_dir_recur($path, $extensions = array()) { $entries = scandir($path.'/'); $files = array(); foreach($entries as $entry) { if ($entry == '.' || $entry == '..') continue; $_path = $path.'/'.$entry; if(is_file($_path)) { if (!empty($extensions)) { $ext = pathinfo($filename, PATHINFO_EXTENSION); if (!in_array($ext, $extensions)) continue; } $files[] = $_path; } else if (is_dir($_path)) { $files = array_merge($files, self::get_files_from_dir_recur($path, $extensions)); } } return $files; } |
W zasadzie to samo można osiągnąć za pomocą iteratorów z biblioteki [SPL](http://www.php.net/~helly/php/ext/spl/):
function get_files_from_dir($path, $extensions = array()) { $files = array(); $it = new DirectoryIterator($path); foreach($it as $file) { $filename = $file->getFilename(); $ext = pathinfo($filename, PATHINFO_EXTENSION); if ($file->isFile() && (empty($extensions) || in_array($ext, $extensions))) { $files[] = $file->getPathname(); } } return $files; } |
i wersja rekurencyjna
function get_files_from_dir_recur($path, $extensions = array()) { $files = array(); $it = new RecursiveDirectoryIterator($path); foreach(new RecursiveIteratorIterator($it) as $file) { $filename = $file->getFilename(); $ext = pathinfo($filename, PATHINFO_EXTENSION); if ($file->isFile() && (empty($extensions) || in_array($ext, $extensions))) { $files[] = $file->getPathname(); } } return $files; } |
Funkcja glob jest jest najprostsza w użyciu. Funkcja z użyciem scandir sprawdza się kiedy glob zawodzi i jest szybsza od iteratorów, które dla każdego znalezionego pliku powołują do życia obiekt.
Kiedy sięgać po iteratory i czy w ogóle? W podanych przeze mnie przykładach interesują nas jedynie ścieżki do plików, tymczasem iteratory zwracają pliki w formie obiektów [SplFileInfo](http://pl.php.net/manual/en/class.splfileinfo.php) z których można wyciągnąć dużo więcej informacji o plikach. Niekiedy może się to przydać i wtedy użycie iteratorów jest zasadne. Jeśli jednak chcemy otrzymać jedynie listę plików wtedy scandir jest lepszym rozwiązaniem bo szybszym.
Funkcja scandir i iteratory są dostępne dopiero od 5 wersji PHP. W PHP4 zawartość katalogu możymy odczytać dzięki funkcji [opendir](http://pl.php.net/manual/en/function.opendir.php).
function get_files_from_dir($path, $extensions = array()) { $files = array(); if (!is_dir($path)) { return $files; } if ($dh = opendir($path)) { while (($file = readdir($dh)) !== false) { $ext = pathinfo($file, PATHINFO_EXTENSION); if (empty($extensions) || in_array($ext, $extensions)) { $files[] = $path.'/'.$file; } } closedir($dh); } return $files; } |