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

Возможный дубликат:
PHP SPL RecursiveDirectoryIterator RecursiveIteratorIterator, восстанавливающий полное дерево

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

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

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

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

ОБНОВИТЬ:

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

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

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

Как вы можете себе представить, это довольно обычная вещь, которая вам нужна, когда вы пишете программное обеспечение, и 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) ); 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 выходит из ее гибкости. То, что не было описано выше, называется FilterIterator s. Я подумал, что я добавлю еще один пример, который использует два самонаписанных из них, помещенных друг в друга, чтобы объединить их.

  • Один из них – отфильтровать все файлы и каталоги, начинающиеся с точки (считаются скрытыми файлами в системах 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 немного отличается. Особенно важна часть об фильтрах:

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

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

Код для этих фильтров довольно прямолинейный, они работают с функцией accept которая является либо true либо false которая должна принимать или отфильтровывать:

 class VisibleOnlyFilter extends RecursiveFilterIterator { public function accept() { $fileName = $this->getInnerIterator()->current()->getFileName(); $firstChar = $fileName[0]; return $firstChar !== '.'; } } class FilesOnlyFilter extends RecursiveFilterIterator { public function accept() { $iterator = $this->getInnerIterator(); // allow traversal if ($iterator->hasChildren()) { return true; } // filter entries, only allow true files return $iterator->current()->isFile(); } } 

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

И еще один примерный выход с $rootpath отключен:

 test.html test.rss tests/test-pad-2.php tests/test-pad-3.php tests/test-pad-4.php tests/test-pad-5.php tests/test-pad-6.php tests/test-pad.php TLD/PSL/C/dkim-regdom.c TLD/PSL/C/dkim-regdom.h TLD/PSL/C/Makefile TLD/PSL/C/punycode.pl TLD/PSL/C/test-dkim-regdom.c TLD/PSL/C/test-dkim-regdom.sh TLD/PSL/C/tld-canon.h TLD/PSL/generateEffectiveTLDs.php 

Не более .git или .svn обход каталога или список файлов типа .builtpath или .project .


Примечание для FilesOnlyFilter и LEAVES_ONLY : фильтр явно запрещает использование каталогов и ссылок на SplFileInfo объекта SplFileInfo ( только обычные файлы, которые существуют ). Таким образом, это настоящая фильтрация на основе файловой системы.
Другой метод, чтобы получать только записи, отличные от каталогов, с RecursiveIteratorIterator LEAVES_ONLY из-за стандартного значения LEAVES_ONLY (здесь также используется в примерах). Этот флаг не работает как фильтр и не зависит от основного итератора. Он просто указывает, что итерация не должна возвращать ветви ( здесь: каталоги в случае итератора каталогов).

Если вы работаете в 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