Pobieranie listy plików o wybranym rozszerzeniu w PHP

Podziel się z innymi!

    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;
    }
    Podziel się z innymi!

      Posted in PHP by Zbigniew Heintze · Tag: