PHP скрипт для циклического прохождения всех файлов в каталоге?

131

Я ищу сценарий PHP, который просматривает все файлы в каталоге, чтобы я мог делать что-то с именем файла, например форматировать, печатать или добавлять его в ссылку. Я хотел бы иметь возможность сортировать файлы по имени, типу или дате создания / добавления / изменения. (Представьте себе причудливый каталог «index».) Я также хотел бы иметь возможность добавлять исключения в список файлов, таких как сам сценарий или другие «системные» файлы. (Как .и .."каталоги".)

Поскольку я хотел бы иметь возможность модифицировать скрипт, мне больше интересно посмотреть документы PHP и научиться писать их самостоятельно. Тем не менее, если есть какие-либо существующие сценарии, учебные пособия и тому подобное, пожалуйста, дайте мне знать.

Моше
источник

Ответы:

245

Вы можете использовать DirectoryIterator . Пример из руководства по php:

<?php
$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo) {
    if (!$fileinfo->isDot()) {
        var_dump($fileinfo->getFilename());
    }
}
?>
Morfildur
источник
3
Примечание: на многих серверах SPL не установлен, поэтому вы не сможете использовать класс DirectoryIterator (см. Мой альтернативный пост ниже). Используйте это, если можете!
NexusRex
4
Примечание [2]: Убедитесь, что вы понимаете, что приведенная dirname()выше функция получит родительскую папку по любому пути, который вы туда укажете. В моем случае я предположил, что dirname является оболочкой для имени / пути каталога, поэтому он не нужен.
willdanceforfun 03
Кроме того, если dirname - это большая файловая система, проблемы с памятью очевидны. В моем случае с 1 миллионом файлов приложению требуется ~ 512 МБ оперативной памяти на memory_limit.
abkrim
1
Если вам нужен полный путь, например, /home/examples/banana.jpgиспользуйте$fileinfo->getPathname()
mgutt
Вы можете использовать! $ Fileinfo-> isDir (), чтобы избежать действий с каталогами
LeChatNoir
44

Если у вас нет доступа к классу DirectoryIterator, попробуйте следующее:

<?php
$path = "/path/to/files";

if ($handle = opendir($path)) {
    while (false !== ($file = readdir($handle))) {
        if ('.' === $file) continue;
        if ('..' === $file) continue;

        // do something with the file
    }
    closedir($handle);
}
?>
NexusRex
источник
4
Можете ли вы назвать ситуацию, при которой у вас не было бы доступа к ней?
Jochem Kuijpers
12
Многие устаревшие приложения используют PHP 4, у которого нет доступа к DirectoryIterator.
Джозеф Каллаарс,
1
Зачем '.' === $ файл? Это не Java.
Дэйв Хек 07
2
Дэйв ... Нет, точки совпадают и не продолжают, если не совпадают в PHP. Найдите разницу между == и ===.
JSG
22

Используйте scandir()функцию:

<?php
    $directory = '/path/to/files';

    if (!is_dir($directory)) {
        exit('Invalid diretory path');
    }

    $files = array();
    foreach (scandir($directory) as $file) {
        if ($file !== '.' && $file !== '..') {
            $files[] = $file;
        }
    }

    var_dump($files);
?>
Хордовые
источник
18

Вы также можете использовать FilesystemIterator. Тогда он требует еще меньше кода DirectoryIteratorи автоматически удаляет .и ...

// Let's traverse the images directory
$fileSystemIterator = new FilesystemIterator('images');

$entries = array();
foreach ($fileSystemIterator as $fileInfo){
    $entries[] = $fileInfo->getFilename();
}

var_dump($entries);

//OUTPUT
object(FilesystemIterator)[1]

array (size=14)
  0 => string 'aa[1].jpg' (length=9)
  1 => string 'Chrysanthemum.jpg' (length=17)
  2 => string 'Desert.jpg' (length=10)
  3 => string 'giphy_billclinton_sad.gif' (length=25)
  4 => string 'giphy_shut_your.gif' (length=19)
  5 => string 'Hydrangeas.jpg' (length=14)
  6 => string 'Jellyfish.jpg' (length=13)
  7 => string 'Koala.jpg' (length=9)
  8 => string 'Lighthouse.jpg' (length=14)
  9 => string 'Penguins.jpg' (length=12)
  10 => string 'pnggrad16rgb.png' (length=16)
  11 => string 'pnggrad16rgba.png' (length=17)
  12 => string 'pnggradHDrgba.png' (length=17)
  13 => string 'Tulips.jpg' (length=10)

Ссылка: http://php.net/manual/en/class.filesystemiterator.php

юлианский
источник
5

Вы можете использовать этот код для рекурсивного просмотра каталога :

$path = "/home/myhome";
$rdi = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::KEY_AS_PATHNAME);
foreach (new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::SELF_FIRST) as $file => $info) {
    echo $file."\n";
}
GameScripting
источник
2

glob () имеет условия для сортировки и сопоставления с образцом. Поскольку возвращаемое значение - это массив, вы можете делать все, что вам нужно.

bcosca
источник
1
Это хорошо, если вы не имеете дело с большим количеством файлов ...> 10 000. У вас закончится память.
NexusRex
@NexusRex: Вы также не должны читать 10 000 записей из базы данных, но это выходит за рамки вопроса
bcosca
Согласовано! Однако при чтении из базы данных вы можете разбивать на страницы с помощью «limit» - не такая удача, когда у вас есть каталог с 5 миллионами файлов XML для итерации.
NexusRex
Есть SPL GlobIterator.
przemo_li
2

Для полноты картины (поскольку это, похоже, страница с высоким трафиком), давайте не забудем старую добрую dir()функцию :

$entries = [];
$d = dir("/"); // dir to scan
while (false !== ($entry = $d->read())) { // mind the strict bool check!
    if ($entry[0] == '.') continue; // ignore anything starting with a dot
    $entries[] = $entry;
}
$d->close();
sort($entries); // or whatever desired

print_r($entries);
Sz.
источник