有没有一种方法只使用glob()函数来获取文件?

44
我知道glob可以查找文件夹中的所有文件或仅限于所有目录:
echo "All files:\n";
$all = glob("/*");
var_dump($all);

echo "Only directories\n";
$dirs = glob("/*", GLOB_ONLYDIR);
var_dump($dirs);

但是我没有找到一种高效地只查找单行文件的方法。
$files = array_diff(glob("/*"), glob("/*", GLOB_ONLYDIR));

功能良好,但读取目录两次(即使有一些优化可以使第二次浏览更快)。


1
你可以使用 glob("*.*") 来获取所有文件,但是如果文件夹名称中含有点(.)或文件没有扩展名时,这种方法将不起作用。 - Get Off My Lawn
8个回答

63
我终于找到了一个解决方案:
echo "Only files\n";
$files = array_filter(glob("/*"), 'is_file');
var_dump($files);

但要小心,array_filter会保留数字键:如果需要重新索引数组,请使用array_values

1
不错!使用foreach循环将解决数组过滤器保留数字键的问题。 - Imdad

7

10
大多数情况下这会奏效,但要注意目录名也可能叫做“toto.jpg”,如果你愿意。 - Alain Tiemblo
我了解到,在括号中文件类型之间有空格确实很重要。不要像我一样做,节省些时间吧! - Joe McLean

7
有一种更简单的方法,只需一行代码:
$files = glob("/path/to/directory/*.{*}", GLOB_BRACE);
{*} 表示所有文件结尾,因此是指所有文件,但不包括文件夹!

2
不,{} 会替换文件或文件夹中的任何字符,而不加区分。 - Alain Tiemblo
9
请注意,文件夹的名称中可能包含句点。 - Nux

0

反转正则表达式完成任务。

preg_grep(
    ';^.*(\\\\|/)$;',
    glob("/*", GLOB_MARK),
    PREG_GREP_INVERT
);

\\\\ 是用于 Windows 反斜杠的符号


0

相比于@AlainTiemblo的解决方案,快了10%,因为它不使用额外的is_file检查:

$files = array_filter(glob("/*", GLOB_MARK), function($path){ return $path[ strlen($path) - 1 ] != '/'; });

相反,它使用内置的GLOB_MARK标志向每个目录添加斜杠,通过array_filter()和匿名函数我们能够删除这些条目。

自PHP 7.1.0起支持负数索引,您也可以使用它来代替:

$files = array_filter(glob("/*", GLOB_MARK), function($path){return $path[-1] != '/';});

没有相关的速度提升,但它有助于避免这篇文章中的垂直滚动条 ^^

由于array_filter()保留键名,因此您应该考虑在之后使用array_values()重新索引数组:

$files = array_values($files);

不行!一开始我以为它可以工作,但它也列出了文件夹。 - Jens Törnell
@JensTörnell,php.net上说:“GLOB_MARK”会“在返回的每个目录后添加一个斜杠”,所以如果你得到的是文件夹,那么这可能是glob中的一个错误。你是否测试过glob("/*", GLOB_MARK)来验证你的发现?或者你使用了一个太旧的PHP版本中的$path[-1] - mgutt
不兼容Windows,因为“GLOB_MARK - 将斜杠(在Windows上是反斜杠)添加到每个返回的目录”,而答案仅使用'/'进行检查。 - DrLightman
Jens和DrL:在两个建议答案中都将“/”更改为DIRECTORY_SEPARATOR(PHP 7.0及更高版本与PHP 7.0之前的版本),然后此答案将适用于所有目录分隔符为一个字符的操作系统。我一直使用array_filter作为第二个参数的'is_file',发现它对于典型目录来说非常快,但是如果您有足够大的目录进行全局匹配,则此解决方案确实有效,并且应该稍微快一些。 - Ted Cohen

0
function glob_file_only($path){
    return array_filter(glob($path,GLOB_MARK),function($file){
        return substr($file,-1)!=DIRECTORY_SEPARATOR;
    });
}

这是在其他人的基础上进行的工作。它只需一次而不是两次触及目录,并且适用于Windows和Linux。


-1

这对我有用。 如果有人需要帮助,请参考。

for file_name in glob.glob('**/*', recursive=True):
    # we get all files and dirs
    if os.path.isfile(file_name):
        # we have only the files

问题要求使用PHP,而不是Python。 - Jason

-10
$all = glob("/*.*");

这将列出所有文件名后面带有“.”的内容。基本上,所有文件都会被列出。


17
文件需要拥有扩展名是从什么时候开始的?而且您为什么认为目录名称中不能有点呢? - Daniel Kamil Kozar

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