Search code examples
phpglob

PHP glob with case-insensitive matching


I use glob for finding folders as

$str = "Test Folder";
$folder = glob("$dir/*$str*");

How can I tell glob to match to find the matching folders case-insensitive?

Matching test folder, TEST FOLDER, etc.

NOTE that $str is an unknown input to the script!


Solution

  • May I suggest the build of case-insensitive character ranges on each letter of $str?

    Code: (Demo)

    function glob_i($string){  // this function is not multi-byte ready.
        $result='';  // init the output string to allow concatenation
        for($i=0,$len=strlen($string); $i<$len; ++$i){  // loop each character
            if(ctype_alpha($string[$i])){  // check if it is a letter
                $result.='['.lcfirst($string[$i]).ucfirst($string[$i]).']';  // add 2-character pattern
            }else{
                $result.=$string[$i];  // add non-letter character
            }
        }
        return $result;  // return the prepared string
    }
    $dir='public_html';
    $str='Test Folder';
    
    echo glob_i($str);  // [tT][eE][sS][tT] [fF][oO][lL][dD][eE][rR]
    echo "\n";
    echo "$dir/*",glob_i($str),'*';  // public_html/*[tT][eE][sS][tT] [fF][oO][lL][dD][eE][rR]*
    

    If you require a multibyte version, this is my suggested snippet: (Demo)

    function glob_im($string,$encoding='utf8'){
        $result='';
        for($i=0,$len=mb_strlen($string); $i<$len; ++$i){
            $l=mb_strtolower(mb_substr($string,$i,1,$encoding));
            $u=mb_strtoupper(mb_substr($string,$i,1,$encoding));
            if($l!=$u){
                $result.="[{$l}{$u}]";
            }else{
                $result.=mb_substr($string,$i,1,$encoding);
            }
        }
        return $result;
    }
    $dir='public_html';
    $str='testovací složku';
    
    echo glob_im($str);  // [tT][eE][sS][tT][oO][vV][aA][cC][íÍ] [sS][lL][oO][žŽ][kK][uU]
    echo "\n";
    echo "$dir/*",glob_im($str),'*';  // public_html/*[tT][eE][sS][tT][oO][vV][aA][cC][íÍ] [sS][lL][oO][žŽ][kK][uU]*
    

    Related Stackoverflow page:

    Can PHP's glob() be made to find files in a case insensitive manner?


    p.s. If you don't mind the expense of regex and/or you prefer a condensed one-liner, this will do the same: (Demo)

    $dir='public_html';
    $str='Test Folder';
    echo "$dir/*",preg_replace_callback('/[a-z]/i',function($m){return '['.lcfirst($m[0]).ucfirst($m[0])."]";},$str),'*';  // $public_html/*[tT][eE][sS][tT] [fF][oO][lL][dD][eE][rR]*
    

    and here is the multi-byte version: (Demo)

    $encoding='utf8';
    $dir='public_html';
    $str='testovací složku';
    echo "$dir/*",preg_replace_callback('/\pL/iu',function($m)use($encoding){return '['.mb_strtolower($m[0],$encoding).mb_strtoupper($m[0],$encoding)."]";},$str),'*';  // public_html/*[tT][eE][sS][tT][oO][vV][aA][cC][íÍ] [sS][lL][oO][žŽ][kK][uU]*