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
комбинация приходит из своей гибкости. То, что не было покрыто выше, называется 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
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 (), а затем снова вызвать свою функцию
$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 для чтения структуры вернул это