PHP получает путь к каждому файлу в папке / подпапке в массив? [дубликат]

Возможные Дубликаты:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator получение полного дерева

Я не уверен, с чего начать. Но я должен получить пути ко всем файлам в папке и все содержимое подпапки в путях тоже. Например, если у меня была папка 1, в которой было пять папок, и в каждой папке было 10 MP3 и т. д... Это означает, что мой массив будет найти 50 путей к этим файлам.

позже скажем, я добавил еще одну папку, и в ней было 3 папки, и в каждой папке было 10 изображений.

мой код теперь должен найти 80 путей и сохранить их в массиве.

имеет ли смысл мой вопрос?

обновление:

моим желаемым выходом было бы иметь все эти пути, хранящиеся в одном массиве.

но я бы" хотел", чтобы код был динамическим, то есть, если я позже добавлю еще 10 папок и каждый из них имеет 17 подпапок и каждый папка, имеющая множество различного содержимого. Я хотел бы, чтобы массив содержал пути к файлам всех файлов. Я думаю, это имеет смысл.

3 ответов


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

как вы можете себе представить, это несколько обычная вещь, вам нужно, когда вы пишете программное обеспечение и PHP поддерживает вас с этим. Он предлагает один RecursiveDirectoryIterator так что каталоги могут быть рекурсивно повторяется и стандартный RecursiveIteratorIterator чтобы сделать обход. Затем вы можете легко получить доступ ко всем файлам и каталогам с помощью простой итерации, например через foreach:

$rootpath = '.';
$fileinfos = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootpath)
);
foreach($fileinfos as $pathname => $fileinfo) {
    if (!$fileinfo->isFile()) continue;
    var_dump($pathname);
}

в этом примере в первую очередь указывается каталог, который вы хотите пересечь. Я взял текущий:

$rootpath = '.';

следующая строка кода немного длинная, она создает экземпляр каталог итератор а то итератор-итератор так что древовидная структура может быть пройдена в одном / плоском цикле:

$fileinfos = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($rootpath)
);

эти $fileinfos затем повторяются с помощью простого foreach:

foreach($fileinfos as $pathname => $fileinfo) {

внутри него, есть тест, чтобы пропустить все каталоги от выхода. Это делается с помощью SplFileInfo объект, который повторяется. Он предоставляется рекурсивным итератором каталогов и содержит множество полезных свойств и методов при работе с файлами. Вы также можете например вернуть расширение файла, базовое имя информация о размере и времени и так далее и тому подобное.

if (!$fileinfo->isFile()) continue;

наконец, я просто выведу путь это полный путь к файлу:

var_dump($pathname);

примерный вывод будет выглядеть следующим образом (здесь, в операционной системе windows):

string(12) ".\.buildpath"
string(11) ".\.htaccess"
string(33) ".\dom\xml-attacks\attacks-xml.php"
string(38) ".\dom\xml-attacks\billion-laughs-2.xml"
string(36) ".\dom\xml-attacks\billion-laughs.xml"
string(40) ".\dom\xml-attacks\quadratic-blowup-2.xml"
string(40) ".\dom\xml-attacks\quadratic-blowup-3.xml"
string(38) ".\dom\xml-attacks\quadratic-blowup.xml"
string(22) ".\dom\xmltree-dump.php"
string(25) ".\dom\xpath-list-tags.php"
string(22) ".\dom\xpath-search.php"
string(27) ".\dom\xpath-text-search.php"
string(29) ".\encrypt-decrypt\decrypt.php"
string(29) ".\encrypt-decrypt\encrypt.php"
string(26) ".\encrypt-decrypt\test.php"
string(13) ".\favicon.ico"

если есть подкаталог, который недоступен, следующее вызовет исключение. Это поведение можно контролировать с помощью некоторых флагов, когда инстанцирование RecursiveIteratorIterator:

$fileinfos = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator('.'),
    RecursiveIteratorIterator::LEAVES_ONLY,
    RecursiveIteratorIterator::CATCH_GET_CHILD
);

надеюсь, это было информативно. Вы также можете обернуть это в свой собственный класс и вы также можете предоставить FilterIterator чтобы переместить решение, должен ли файл быть указан или нет из foreach петли.


власть RecursiveDirectoryIterator и RecursiveIteratorIterator комбинация приходит из своей гибкости. То, что не было покрыто выше, называется FilterIterators. Я думал, что добавлю еще один пример, который использует два самописца из них, помещенных друг в друга, чтобы объединить их.

  • один-отфильтровать все файлы и каталоги, которые начинаются с точки (они считаются скрытыми файлами в системах UNIX, поэтому вы не должны давать эту информацию снаружи) и
  • еще один, который фильтрует список только для файлов. Это проверка, которая ранее была внутри командлет foreach.

еще одно изменение в этом примере использования-использовать getSubPathname() функции это возвращает вложенный путь, начинающийся с корневого пути итерации, поэтому тот, который вы ищете.

также я явно добавляю SKIP_DOTS флаг который предотвращает прохождение . и .. (технически не действительно необходимо, потому что фильтры будут фильтровать их, а также они являются каталогами, однако я думаю, что это более правильно) и возвращаются как пути, как UNIX_PATHS Итак, строки путей всегда unix-подобные пути независимо от базовой операционной системы, что обычно является хорошей идеей, если эти значения запрашиваются через HTTP позже, как в вашем случае:

$rootpath = '.';

$fileinfos = new RecursiveIteratorIterator(
    new FilesOnlyFilter(
        new VisibleOnlyFilter(
            new RecursiveDirectoryIterator(
                $rootpath,
                FilesystemIterator::SKIP_DOTS
                    | FilesystemIterator::UNIX_PATHS
            )
        )
    ),
    RecursiveIteratorIterator::LEAVES_ONLY,
    RecursiveIteratorIterator::CATCH_GET_CHILD
);

foreach ($fileinfos as $pathname => $fileinfo) {
    echo $fileinfos->getSubPathname(), "\n";
}

этот пример похож на предыдущий, хотя и как $fileinfos is build немного по-другому настроен. Особенно в рубрике фильтры в городе новое:

    new FilesOnlyFilter(
        new VisibleOnlyFilter(
            new RecursiveDirectoryIterator($rootpath, ...)
        )
    ),

таким образом, итератор каталога помещается в фильтр, а сам фильтр помещается в другой фильтр. Остальные не изменение.

код для этих фильтров довольно прямолинейный, они работают с


Если вы находитесь в linux, и вы не против выполнения команды оболочки, вы можете сделать это все в одной строке

$path = '/etc/php5/*'; // file filter, you could specify a extension using *.ext
$files = explode("\n", trim(`find -L $path`)); // -L follows symlinks

print_r($files);

выход:

Array (
       [0] => /etc/php5/apache2
       [1] => /etc/php5/apache2/php.ini
       [2] => /etc/php5/apache2/conf.d
       [3] => /etc/php5/apache2/conf.d/gd.ini
       [4] => /etc/php5/apache2/conf.d/curl.ini
       [5] => /etc/php5/apache2/conf.d/mcrypt.ini
       etc...
      )

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

http://us3.php.net/glob

$files = dir_scan('/etc/php5/*'); 
print_r($files);

function dir_scan($folder) {
    $files = glob($folder);
    foreach ($files as $f) {
        if (is_dir($f)) {
            $files = array_merge($files, dir_scan($f .'/*')); // scan subfolder
        }
    }
    return $files;
}

любой другой способ требуется гораздо больше кода, чем нужно, чтобы сделать что-то настолько простое


действия такие:

и opendir откроет структуру каталогов

$dh = opendir($dir)

что вы делаете дальше, это читать все, что есть в $dh

$file = readdir($dh)

вы можете найти всю информацию в руководстве php, соответствующую opendir

и googling для чтения структуры вернул это

http://www.codingforums.com/showthread.php?t=71882