Náhrada za funkci glob

Školení, která pořádám

Funkce glob je k dispozici už od PHP 4.3.0, na některých hostinzích je ale z bezpečnostních důvodů zakázaná a neobsahuje ji ani knihovna PHP_Compat (důvodem je pravděpodobně to, že ačkoliv se tato funkce velice jednoduše používá, uvnitř je dosti složitá).

Proto přináším jednodušší náhradu této funkce. Ze znaků masky jsou povolené pouze * (libovolný počet libovolných znaků) a ? (libovolný znak), hvězdička navíc zahrnuje i tečku na začátku souboru, zástupné znaky nejsou povolené v názvech adresářů a chování funkce nelze ovlivnit pomocí druhého parametru, pro základní použití by ale tato funkce stačit mohla.

<?php
/** Jednodušší náhrada funkce glob()
* @param string vyhledávací maska může v názvu souboru obsahovat znak * a ?
* @return array pole obsahující všecny nalezené soubory/adresáře
* @copyright Jakub Vrána, https://php.vrana.cz/
*/
function simple_glob($mask) {
    $dirname = preg_replace('~[^/]*$~', '', $mask);
    $dir = opendir(strlen($dirname) ? $dirname : ".");
    $return = array();
    if ($dir) {
        $pattern = '~^' . strtr(preg_quote($mask, '~'), array('\\*' => '.*', '\\?' => '.')) . '$~';
        while (($filename = readdir($dir)) !== false) {
            if ($filename != "." && $filename != ".." && preg_match($pattern, "$dirname$filename")) {
                $return[] = "$dirname$filename";
            }
        }
        closedir($dir);
        sort($return);
    }
    return $return;
}
?>

V masce se nahradí všechny znaky se speciálním významem v regulárních výrazech a na odpovídající vzor se převede pouze hvězdička a otazník. Takto upravená maska se potom použije pro porovnání se souborem.

Dodatečně jsem zjistil, že kompletní náhrada funkce glob se do PHP_Compat dostala, ale k dispozici je zatím jen v CVS a navíc špatně funguje rozpoznávání jednotlivých částí cesty. Mimo Windows lze pro porovnání použít funkci fnmatch.

Jakub Vrána, Řešení problému, 23.2.2007, diskuse: 9 (nové: 0)

Diskuse

Hds:

Díky, hezká funkce, ukládám do code library ... :)

mach:

Mimochodem, ten samotny zakladni wildcard matching (* a ?) se da v C napsat na pouhych 10 radku:

http://c-faq.com/lib/regex.html

ia:

A nebolo by jednoduchšie a užitočnejsie tam dať namiesto wildcard matches rovno regulárne výrazy?

ikona D1ce:

Pokud například používáte dílo, kde se klasický glob používá hojně jen tak, jak funguje řešení pana Vrány a nechtělo by se vám je přepisovat a ani byste nechtěl napsat skript, který by to udělal za vás, tak asi ne. Jinak to ale není vůbec špatný nápad. Jen ne úplně všichni lidé co kdy psali v php nemusí znát reg. výrazy, ale třeba rozumí wildcards v glob().

karels:

Prosím vás,

kam vložit to, co jste pane Vráno napsal? Mám to vložit někam do template? Jde o dokuWiki...

díky karels

Lubos:

Dobrý den, kam toto vložit, aby funkce glob fungovala? Díky.

krteczek:

nejsem si jistý, ale něco jako:
<?php

if(!function_exists('glob'))
    {
        /** Jednodušší náhrada funkce glob()
        * @param string $mask vyhledávací maska může v názvu souboru obsahovat znak * a ?
        * @return array pole obsahující všecny nalezené soubory/adresáře
        * @copyright Jakub Vrána, http://php.vrana.cz
        */
        function glob($mask)
            {
                $dirname = preg_replace('~[^/]*$~', '', $mask);
                $dir = opendir(strlen($dirname) ? $dirname : ".");
                $return = array();
                if ($dir)
                    {
                        $pattern = '~^' . strtr(preg_quote($mask, '~'), array('\\*' => '.*', '\\?' => '.')) . '$~';
                        while (($filename = readdir($dir)) !== false)
                            {
                                if ($filename != "." && $filename != ".." && preg_match($pattern, "$dirname$filename"))
                                    {
                                        $return[] = "$dirname$filename";
                                    }
                            }
                        closedir($dir);
                        sort($return);
                    }
                return $return;
            }
    }
?>
by snad mohlo fungovat

HTMLHERGOT:

Zajímalo mě, které z těchto dvou řešení je rychlejší.
http://stackoverflow.com/questions/2763290/…-or-opendir

HTMLHERGOT:

Jako třetí řešení by mohla posloužit třída DirectoryIterator.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.