Glob () - сортировать массив файлов по дате и времени последнего изменения

Я пытаюсь отобразить массив файлов по дате (последнее изменение).

Я сделал эту покупку, перебирая массив и отсортировав его в другой массив, но есть ли более простой (более эффективный) способ сделать это?

Вы нашли это? (Только что выполнил поиск в Google по названию вашего вопроса): webdeveloper.com/forum/showthread.php?t=188670

John 24.09.2008 05:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
51
1
41 563
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Warningcreate_function() has been DEPRECATED as of PHP 7.2.0. Relying on this function is highly discouraged.

Ради потомков, если сообщение на форуме, связанное с принятым ответом, потеряно или непонятно для некоторых, потребуется соответствующий код:

<?php

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

?>

Протестировал это в моей системе и подтвердил, что он сортирует по времени файла по желанию. Я использовал аналогичный подход (написанный на Python) для определения последних обновленных файлов на моем веб-сайте.

Работал красиво. Мне нужен был обратный порядок, поэтому я заменил $ a на $ b в поле определения функции. Спасибо, Джей!

AVProgrammer 12.01.2012 02:53

Этот код обращается к файловой системе каждый раз, когда выполняется сравнение (несколько раз для каждого файла). В зависимости от того, где находится ваша файловая система, это может быть очень медленным. Кроме того, если какой-либо из файлов записывается во время сортировки, то изменение времени файла может привести к странным результатам сортировки в зависимости от алгоритма, используемого usort. Я бы порекомендовал другой ответ, который позволяет избежать всех этих проблем.

Matt 27.06.2013 22:43

Если вы используете PHP 5.3.0 или новее, вместо этого следует использовать нативную анонимную функцию. php.net/create_function

xd6_ 29.01.2015 17:33

<?php
$items = glob('*', GLOB_NOSORT);
array_multisort(array_map('filemtime', $items), SORT_NUMERIC, SORT_DESC, $items);

Нет смысла передавать результат array_map в качестве аргумента, предназначенного для передачи по ссылке. Вы его отсортируете, но что потом? У тебя его больше нет.

Okonomiyaki3000 15.04.2014 09:47

Результат array_map используется для сортировки массива $items, который также передается по ссылке.

Alf Eaton 16.04.2014 00:34

Понятно. Думаю, это сработает, подобный подход даже задокументирован на странице array_multisort на php.net. Я думаю, что есть более подходящие функции для этой задачи, но я заберу свой голос против. Или я бы, если бы мог ... извините.

Okonomiyaki3000 16.04.2014 09:18

Протестировано и неправильно сортируется в реальной жизни, несмотря на то, что выглядит привлекательно.

Viktor Joras 25.06.2018 10:17

@ViktorJoras Можете ли вы разместить ссылку на свой тестовый код?

Alf Eaton 13.07.2018 16:22

Я бы, вероятно, использовал эту технику, потому что таким образом filemtime() никогда не вызывается более одного раза для данного файла. Я бы использовал UV-фильтр для этого ответа, но у меня есть жесткая политика, которая не позволяет мне использовать UV-фильтр для необъяснимых ответов.

mickmackusa 12.10.2020 03:44

Это решение такое же, как принятый ответ, обновленное анонимной функцией 1:

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

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

1Анонимные функции были введены в PHP в 2010 году. Оригинальный ответ датирован 2008 годом.

Поскольку сейчас 2019 год, это должен быть принятый ответ. PHP 7 больше не поддерживает "create_function" ... поэтому лучшим решением по всем направлениям является использование анонимной функции (или ссылки).

Matt Kenefick 09.01.2019 19:07

Я знаю, что эта ветка устарела, но это можно сделать с большей производительностью. 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 );

Поскольку PHP 7.4, лучшим решением является использование пользовательской сортировки со стрелочной функцией:

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

Вы также можете использовать оператор космического корабля, который работает для всех видов сравнений, а не только для целочисленных. В этом случае это не будет иметь никакого значения, но рекомендуется использовать его во всех операциях сортировки.

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

Если вы хотите отсортировать в обратном порядке, вы можете отменить условие:

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

2020 год - если вам важна производительность, не используйте glob()!

Если вы хотите сканировать много файлов в папке без специальных подстановочных знаков, наборы правил или любой exec(),

Я предлагаю scandir() или readdir().

glob() намного медленнее, в Windows еще медленнее.


quote by:aalfiann

why glob seems slower in this benchmark? because glob will do recursive into sub dir if you write like this "mydir/*".

just make sure there is no any sub dir to make glob fast.

"mydir/*.jpg" is faster because glob will not try to get files inside sub dir.


benchmark:glob() vs scandir()

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


discussion:readdir() vs scandir()

readdir vs scandir (stackoverflow)


readdir() or scandir() combined with these, for pretty neat performance.

PHP 7.4

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

source:https://stackoverflow.com/a/60476123/3626361

PHP 5.3.0 and newer

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

source:https://stackoverflow.com/a/35925596/3626361


if you wanna go even deeper the rabbit hole:

The DirectoryIterator


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

https://www.php.net/manual/en/directoryiterator.construct.php (read the comments!)

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

Difference between DirectoryIterator and 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']) );

Другие вопросы по теме