可以使 PHP 的 glob() 以不区分大小写的方式查找文件吗?

Posted

技术标签:

【中文标题】可以使 PHP 的 glob() 以不区分大小写的方式查找文件吗?【英文标题】:Can PHP's glob() be made to find files in a case insensitive manner? 【发布时间】:2011-02-01 00:18:49 【问题描述】:

我想要一个目录中的所有 CSV 文件,所以我使用

glob('my/dir/*.CSV')

但是,这不会找到具有小写 CSV 扩展名的文件。

可以使用

glob('my/dir/*.CSV,csv', GLOB_BRACE);

但是有没有办法允许所有混合大小写版本?还是这只是glob() 的限制?

【问题讨论】:

请注意,glob() 在 Windows 中实际上是不区分大小写的(可能还有其他不区分大小写的文件系统)。 那不是真的。 glob("*.CSV") 只会查找大写文件,而glob("*.csv") 只会查找小写文件。 --- 在 windows7 中使用 php 5.3.8 测试 【参考方案1】:

你可以这样做

$files = glob('my/dir/*');

$csvFiles =  preg_grep('/\.csv$/i', $files);

【讨论】:

非常干净和灵活。 同意。看来您不能将 GLOB_BRACE 与字符范围结合起来,所以我最终使用 glob+preg_grep 一次对多种文件格式进行不区分大小写的搜索。感谢您的提示! 这是 imo 最有用的解决方案。 这会比普通且区分大小写的glob 更慢或占用更多内存吗? @tjespe 理论上更慢且内存更多,因为有一个额外的迭代来过滤原始数组和创建的新数组。【参考方案2】:

全局模式支持字符范围:

glob('my/dir/*.[cC][sS][vV]')

【讨论】:

但它不会也匹配任何以“.Csv”或“.CsV”结尾的文件吗?但这是一个支点:我正在寻找的是一种模式,它将以不区分大小写的方式(jpg、JPG、png、PNG 等)匹配所有图像文件。 @JohnK:“但是有没有办法允许所有混合大小写的版本?”【参考方案3】:

glob('my/dir/*.[cC][sS][vV]') 应该这样做。是的,有点丑。

【讨论】:

【参考方案4】:

您可以编写自己的不区分大小写的 glob。这是来自我写的一个个人网络图书馆:

/** PHP has no case insensitive globbing
 * so we have to build our own.
 *
 * $base will be the initial part of the path which doesn't need case insensitive
 * globbing.
 * Suffix is similar - it will not be made insensitive
 * Make good use of $base and $suffix to keep $pat simple and fast in use.
 */
    function ciGlob($pat, $base = '', $suffix = '')
    
        $p = $base;
        for($x=0; $x<strlen($pat); $x++)
        
            $c = substr($pat, $x, 1);
            if( preg_match("/[^A-Za-z]/", $c) )
            
                $p .= $c;
                continue;
            
            $a = strtolower($c);
            $b = strtoupper($c);
            $p .= "[$a$b]";
        
        $p .= $suffix;
        return glob($p);
    

【讨论】:

【参考方案5】:

你也可以全选后过滤掉文件

foreach(glob('my/dir/*') as $file)
    $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
    if(!in_array($ext, array('csv')))
        continue;
    
    ... do stuff ...

就性能而言,如果文件夹中有 100 万个非 csv 文件,这可能不是最佳选择。

【讨论】:

【参考方案6】:

我听说有一个函数可以这样使用: 试试这是否适合你!

<?php
$pattern = sql_regcase("*.txt");
glob($pattern);
?>

【讨论】:

有趣。但它的使用已被弃用。【参考方案7】:

要使其适用于所有扩展,请使用:

$extension = 'some_extension';
glob('my/dir/*.preg_replace('/(\w)/e', "'['.strtoupper($1).strtolower($1).']'", $extension));

【讨论】:

我不能代表投票给你的人,但有几点(希望有帮助):(1)你的路径字符串缺少结束 ',以及(2)PCRE e (eval) 标志自 PHP 5.5 起已弃用,并在 7 中删除,两者都比这个答案更早。不鼓励使用它。 preg_replace() 是不必要的使用。您可以explode()map(),返回大小写变体,然后返回join()【参考方案8】:

来到此链接以获取包含多个文件的 glob。虽然它对 OP 没有帮助,但它可能会帮助到这里的其他人。

$file_type = 'csv,jpeg,gif,png,jpg';
$i = '0';
foreach(explode(",",$file_type) as $row)
    if ($i == '0') 
        $file_types = $row.','.strtoupper($row);
     else 
        $file_types .= ','.$row.','.strtoupper($row);
    
    $i++;


$files = glob($dir."*.".$image_types."",GLOB_BRACE);

【讨论】:

$i'0'?为什么? 0 是数组的第一个元素 我的意思是,您将它用作循环索引,但将其定义为字符串。 它被称为数字字符串和带有算术运算符的函数。【参考方案9】:

此代码仅适用于获取图像且不区分大小写。

图片列表:

image1.jpg image2.JPG image3.jpg image4.GIF $imageOnly = '*.[jJ][pP][gG],[jJ][pP][eE][gG],[pP][nN][gG],[gG][iI][fF]'; $arr_files = (array) glob($path . $imageOnly, GLOB_BRACE);

也许它看起来很丑,但你只需要声明一次 $imageOnly 并且可以在需要的地方使用它。您还可以声明 $jpgOnly 等。

我什至做了一个函数来创建这个模式。

/*--------------------------------------------------------------------------
 * create case insensitive patterns for glob or simular functions
 * ['jpg','gif'] as input
 * converted to: *.[Jj][Pp][Gg],[Gg][Ii][Ff]
 */
function globCaseInsensitivePattern($arr_extensions = []) 
   $opbouw = '';
   $comma = '';
   foreach ($arr_extensions as $ext) 
       $opbouw .= $comma;
       $comma = ',';
       foreach (str_split($ext) as $letter) 
           $opbouw .= '[' . strtoupper($letter) . strtolower($letter) . ']';
       
   
   if ($opbouw) 
       return '*.' . $opbouw . '';
   
   // if no pattern given show all
   return '*';
 // end function

$arr_extensions = [
        'jpg',
        'jpeg',
        'png',
        'gif',
    ];
$imageOnly = globCaseInsensitivePattern($arr_extensions);
$arr_files = (array) glob($path . $imageOnly, GLOB_BRACE);

【讨论】:

【参考方案10】:

根据 Alex 的提示,这通常会有所帮助:

function glob_files ($d, $e)

    $files = preg_grep ("/$e\$/i", glob ("$d/*"));
    sort ($files)
    return $files;

其中$d 是目录,$e 是扩展名。

【讨论】:

以上是关于可以使 PHP 的 glob() 以不区分大小写的方式查找文件吗?的主要内容,如果未能解决你的问题,请参考以下文章

glob及IO重定向

在 Linux 上忽略 glob() 中的大小写

sqlite模糊查询

Python3标准库:fnmatch UNIX式glob模式匹配

Swift中不区分大小写的字典

SQLite语法