glob() - 按日期排序

col*_*ole 47 php

我正在尝试按日期顺序显示一个文件数组(最后修改).

我已经完成了这个购买循环数组并将其排序到另一个数组,但是有更简单(更有效)的方法吗?

Jay*_*Jay 94

为了后代,如果在接受的答案中链接的论坛帖子丢失或某些人不清楚,所需的相关代码是:

<?php

$myarray = glob("*.*");
usort($myarray, create_function('$a,$b', 'return filemtime($a) - filemtime($b);'));

?>
Run Code Online (Sandbox Code Playgroud)

在我的系统上对此进行了测试并验证了它根据需要按文件mtime排序.我使用类似的方法(用Python编写)来确定我网站上的最新更新文件.

  • 工作得很漂亮.我想要相反的顺序,所以我在函数定义字段中用$ b换了$ a.谢谢Jay! (12认同)
  • 我刚刚用过这个.对于后人确实! (4认同)
  • 如果您使用的是PHP 5.3.0或更高版本,则应使用本机匿名函数.http://php.net/create_function (4认同)
  • 每次进行比较时,此代码都在访问文件系统(每个文件多次).根据文件系统的位置,可能会非常慢.此外,如果在排序期间写入任何文件,则更改文件时间可能会导致奇怪的排序结果,具体取决于usort使用的算法.我会推荐[其他答案](http://stackoverflow.com/a/3298787/706054),这可以避免所有这些问题. (3认同)

Alf*_*ton 36

<?php
$items = glob('*', GLOB_NOSORT);
array_multisort(array_map('filemtime', $items), SORT_NUMERIC, SORT_DESC, $items);
Run Code Online (Sandbox Code Playgroud)

  • 我知道了。我想这会奏效,类似的方法甚至记录在 php.net 的 `array_multisort` 页面上。我认为这项任务有更合适的功能,但我会收回我的反对票。或者如果我可以的话我会......对不起。 (2认同)
  • @ Okonomiyaki3000:我取代了你的downvote,因为它是无知的. (2认同)

fus*_*n3k 16

此解决方案与接受的答案相同,使用匿名函数1更新:

$myarray = glob("*.*");

usort( $myarray, function( $a, $b ) { return filemtime($a) - filemtime($b); } );
Run Code Online (Sandbox Code Playgroud)

1 2010年,PHP中引入了匿名函数.原始答案是2008年.

  • 由于现在是2019年,这应该是公认的答案。PHP 7不再允许“ create_function” ..因此,最好的解决方案是使用匿名函数(或引用) (3认同)

Seb*_*ian 6

这可以通过更好的性能来完成。接受的答案usort()中会调用filemtime()很多次。PHP使用快速排序算法,其平均性能为1.39*n*lg(n). 该算法每次比较调用filemtime()两次,因此我们将有大约 28 次调用用于 10 个目录条目,556 次调用用于 100 个条目,8340 次调用用于 1000 个条目等。下面的代码对我来说效果很好,并且性能很好:

exec ( stripos ( PHP_OS, 'WIN' ) === 0 ? 'dir /B /O-D *.*' : 'ls -td1 *.*' , $myarray );
Run Code Online (Sandbox Code Playgroud)


Dha*_*man 6

PHP 7.4 开始,最好的解决方案是使用带有箭头函数的自定义排序:

usort($myarray, fn($a, $b) => filemtime($a) - filemtime($b));
Run Code Online (Sandbox Code Playgroud)

您还可以使用适用于各种比较的太空船运算符,而不仅仅是整数比较。在这种情况下它不会有任何区别,但在所有排序操作中使用它是一个很好的做法。

usort($myarray, fn($a, $b) => filemtime($a) <=> filemtime($b));
Run Code Online (Sandbox Code Playgroud)

如果你想以相反的顺序排序,你可以否定条件:

usort($myarray, fn($a, $b) => -(filemtime($a) - filemtime($b)));
// or 
usort($myarray, fn($a, $b) => -(filemtime($a) <=> filemtime($b)));
Run Code Online (Sandbox Code Playgroud)


小智 5

2020 年 - 如果您关心性能,请考虑不要使用glob()

如果您想扫描文件夹中的大量文件,而不需要特殊的通配符、规则集或任何exec()

我建议scandir(),或者readdir()

glob()速度慢很多,在 Windows 上更慢。


引用者: aalfinn

为什么 glob 在此基准测试中看起来较慢?因为如果你这样写,glob 将会递归到子目录中"mydir/*"

只需确保没有任何子目录可以使 glob 快速运行。

"mydir/*.jpg"速度更快,因为 glob 不会尝试获取子目录中的文件。


基准: glob()对比scandir()

http://www.spudsdesign.com/benchmark/index.php?t=dir2(外部)


讨论: readdir()对比scandir()

readdir 与 scandir (stackoverflow)


readdir()或者scandir()与这些结合起来,以获得非常整洁的性能。

PHP 7.4

usort( $myarray, function( $a, $b ) { return filemtime($a) - filemtime($b); } );

来源: https ://stackoverflow.com/a/60476123/3626361

PHP 5.3.0 及更高版本

usort($myarray, fn($a, $b) => filemtime($a) - filemtime($b));

来源: https ://stackoverflow.com/a/35925596/3626361


如果你想深入兔子洞:

目录迭代器


https://www.php.net/manual/en/class.directoryiterator.php

https://www.php.net/manual/en/directoryiterator.construct.php(阅读评论!)

http://paulyg.github.io/blog/2014/06/03/directoryiterator-vs-filesystemiterator.html

DirectoryIterator 和 FileSystemIterator 的区别


最后但并非最不重要的一点是我的演示!

<?php
function files_attachment_list($id, $sort_by_date = false, $allowed_extensions = ['png', 'jpg', 'jpeg', 'gif', 'doc', 'docx', 'pdf', 'zip', 'rar', '7z'])
{
    if (empty($id) or !is_dir(sprintf('files/%s/', $id))) {
        return false;
    }
    $out = [];
    foreach (new DirectoryIterator(sprintf('files/%s/', $id)) as $file) {
        if ($file->isFile() == false || !in_array($file->getExtension(), $allowed_extensions)) {
            continue;
        }

        $datetime = new DateTime();
        $datetime->setTimestamp($file->getMTime());
        $out[] = [
            'title' => $file->getFilename(),
            'size' => human_filesize($file->getSize()),
            'modified' => $datetime->format('Y-m-d H:i:s'),
            'extension' => $file->getExtension(),
            'url' => $file->getPathname()
        ];
    }

    $sort_by_date && usort($out, function ($a, $b) {
        return $a['modified'] > $b['modified'];
    });

    return $out;
}

function human_filesize($bytes, $decimals = 2)
{
    $sz = 'BKMGTP';
    $factor = floor((strlen($bytes) - 1) / 3);
    return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}

// returns a file info array from path like '/files/123/*.extensions'
// extensions = 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx', 'pdf', 'zip', 'rar', '7z'
// OS specific sorting
print_r( files_attachment_list(123) );

// returns a file info array from the folder '/files/456/*.extensions'
// extensions = 'txt', 'zip'
// sorting by modified date (newest first)
print_r( files_attachment_list(456, true, ['txt','zip']) );
Run Code Online (Sandbox Code Playgroud)