PHP的glob()函数是否可以以不区分大小写的方式查找文件?

48

我想要获取一个目录下的所有CSV文件,所以我使用了

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

然而,这种方法无法找到扩展名为小写CSV的文件。

可以使用

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

但是否有一种方法可以允许所有大小写混合的版本?或者这只是 glob() 的一个限制?


请注意,glob() 在 Windows(以及可能的其他不区分大小写的文件系统)中实际上是不区分大小写的。 - Simon East
1
这不是真的。glob("*.CSV") 只会找到大写文件,而 glob("*.csv") 只会找到小写文件。--- 在 Windows7 上测试过,使用的是 PHP 5.3.8。 - Radon8472
11个回答

67

通配符支持字符范围:

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

1
但它不会匹配任何以".Csv"或".CsV"结尾的文件吗?但那只是旁白:我正在寻找一种模式,以不区分大小写的方式匹配所有图像文件(jpg、JPG、png、PNG等)。 - JohnK
4
@JohnK:「但有没有办法允许所有混合大小写版本?」 - Ignacio Vazquez-Abrams

44

你可以这样做

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

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

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

7

glob('my/dir/*.[cC][sS][vV]') 可以实现此功能。是的,这有点丑陋。


2

在选择所有文件后,您还可以进行筛选

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

就性能而言,如果您的文件夹中有100万个不是csv格式的文件,则这可能不是最佳选项。


2
这段代码可以获取图片列表,不区分大小写。 图片列表:
  • 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);

0

来到这个链接是为了使用多个文件的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' - alex
数组中的第一个元素是0。 - user3058870
1
我的意思是,你正在将它用作循环索引,但将其定义为字符串。 - alex
它被称为数字字符串,并且可以使用算术运算符进行操作。 - user3058870

0

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

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

有趣。不过它的使用已经被弃用了。 - alex

0

补充Ignacio的答案,如果你想使用一个不区分大小写的变量,可以通过将变量拆分为字节并自动准备字符范围来实现:

$dir = "my/dir/*";
$var = ".cSv"; // example

$var_array = str_split($var); // split into bytes
$case_insensitive_var = '';
foreach($var_array as $var_byte){
    $case_insensitive_var .= '['.strtolower($var_byte).strtoupper($var_byte).']';
}

$dirs = glob($dir.$case_insensitive_var, GLOB_BRACE);

只需更改$dir和$var,即可准备就绪。


0
你可以编写自己的不区分大小写的glob。这是我编写的一个个人Web库中的内容:
/** 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);
    }

0

在Alex的提示基础上,这可能会有所帮助:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接