问题
I have set up a basic script that is posting an array of paths to find template files inside them; currently it's only searching two levels deep and I'm having some troubles getting my head around the logic for an extensive loop to iterate all child directories until the length is 0.
So if I have a structure like this:
./components
./components/template.html
./components/template2.html
./components/side/template.html
./components/side/template2.html
./components/side/second/template.html
./components/side/second/template2.html
./components/side/second/third/template.html
./components/side/second/third/template2.html
It's only searching up to the "side" directory for .html files when ideally I want it to check all child directories and the passed directory for .html files. Here is my working code so far:
<?php
function getFiles($path){
$dh = opendir($path);
foreach(glob($path.'/*.html') as $filename){
$files[] = $filename;
}
if (isset($files)) {
return $files;
}
}
foreach ($_POST as $path) {
foreach (glob($path . '/*' , GLOB_ONLYDIR) as $secondLevel) {
$files[] = getFiles($secondLevel);
}
$files[] = getFiles($path);
}
sort($files);
print_r(json_encode($files));
?>
回答1:
PHP has the perfect solution for you built in.
Example
// Construct the iterator
$it = new RecursiveDirectoryIterator("/components");
// Loop through files
foreach(new RecursiveIteratorIterator($it) as $file) {
if ($file->getExtension() == 'html') {
echo $file;
}
}
Resources
- DirectoryIterator - Manual
回答2:
PHP 5 introduces iterators to iterate quickly through many elements.
You can use RecursiveDirectoryIterator to iterate recursively through directories.
You can use RecursiveIteratorIterator on the result to have a flatten view of the result.
You can use RegexIterator on the result to filter based on a regular expression.
$directory_iterator = new RecursiveDirectoryIterator('.');
$iterator = new RecursiveIteratorIterator($directory_iterator);
$regex_iterator = new RegexIterator($iterator, '/\.php$/');
$regex_iterator->setFlags(RegexIterator::USE_KEY);
foreach ($regex_iterator as $file) {
echo $file->getPathname() . PHP_EOL;
}
With iterators, there are lot of ways to do the same thing, you can also use a FilterIterator (see the example on the page)
For instance, if you want to select the files modified this week, you can use the following:
$directory_iterator = new RecursiveDirectoryIterator('.');
$iterator = new RecursiveIteratorIterator($directory_iterator);
class CustomFilterIterator extends FilterIterator {
function accept() {
$current=$this->getInnerIterator()->current();
return ($current->isFile()&&$current->getMTime()>time()-3600*24*7);
}
}
$filter_iterator=new CustomFilterIterator($iterator);
foreach ($filter_iterator as $file) {
echo $file->getPathname() . PHP_EOL;
}
回答3:
Another solution is using Finder component from Symfony. It's tested and proven code. Take a look at it here: http://symfony.com/doc/current/components/finder.html
回答4:
Here is working code which scans given directory $dir and all of its sub directories to any levels and return list of html files and folders containing them.
<?php
function find_all_files($dir)
{
if(!is_dir($dir)) return false;
$pathinfo = '';
$root = scandir($dir);
foreach($root as $value)
{
if($value === '.' || $value === '..') {continue;}
if(is_file("$dir/$value")) {
$pathinfo = pathinfo($dir.'/'.$value);
if($pathinfo['extension'] == 'html') {
$result[]="$dir/$value";
}
continue;
}
foreach(find_all_files("$dir/$value") as $value)
{
$result[]=$value;
}
}
return $result;
}
//call function
$res = find_all_files('physical path to folder');
print_r($res);
?>
回答5:
Universal File search in folder, sub-folder :
function dirToArray($dir,$file_name) {
$result = array();
$cdir = scandir($dir);
foreach ($cdir as $key => $value)
{
if (!in_array($value,array(".","..")))
{
if (is_dir($dir . DIRECTORY_SEPARATOR . $value))
{
$result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value,$file_name);
}
else
{
if($value == $file_name){
$result[] = $value;
}
}
}
}
return $result;
}
define('ROOT', dirname(__FILE__));
$file_name = 'template.html';
$tree = dirToArray(ROOT,$file_name);
echo "<pre>".print_r($tree,1)."</pre>";
OUTPUT :
Array
(
[components] => Array
(
[side] => Array
(
[second] => Array
(
[0] => template.html
[third] => Array
(
[0] => template.html
)
)
[0] => template.html
)
[0] => template.html
)
[0] => template.html
)
回答6:
Alternative of my previous answer :
$dir = 'components';
function getFiles($dir, &$results = array(), $filename = 'template.html'){
$files = scandir($dir);
foreach($files as $key => $value){
$path = realpath($dir.'/'.$value);
if(!is_dir($path)) {
if($value == $filename)
$results[] = $path;
} else if($value != "." && $value != "..") {
getFiles($path, $results);
}
}
return $results;
}
echo '<pre>'.print_r(getFiles($dir), 1).'</pre>';
OUTPUT :
Array
(
[0] => /web/practise/php/others/test7/components/side/second/template.html
[1] => /web/practise/php/others/test7/components/side/second/third/template.html
[2] => /web/practise/php/others/test7/components/side/template.html
[3] => /web/practise/php/others/test7/components/template.html
)
回答7:
Here is a generic solution:
function parseDir($dir, &$files=array(), $extension=false){
if(!is_dir($dir)){
$info = pathinfo($dir);
// add all files if extension is set to false
if($extension === false || (isset($info['extension']) && $info['extension'] === $extension)){
$files[] = $dir;
}
}else{
if(substr($dir, -1) !== '.' && $dh = opendir($dir)){
while($file = readdir($dh)){
parseDir("$dir/$file", $files, $extension);
}
}
}
}
$files = array();
parseDir('components', $files, 'html');
var_dump($files);
OUTPUT
php parseDir.php
array(7) {
[0]=>
string(25) "components/template2.html"
[1]=>
string(29) "components/side/template.html"
[2]=>
string(30) "components/side/template2.html"
[3]=>
string(36) "components/side/second/template.html"
[4]=>
string(37) "components/side/second/template2.html"
[5]=>
string(42) "components/side/second/third/template.html"
[6]=>
string(43) "components/side/second/third/template2.html"
}
来源:https://stackoverflow.com/questions/25909820/how-to-recursively-iterate-through-files-in-php