在面试中我们经常遇到这个题目:用PHP遍历一个文件夹下的所有文件和子文件夹。
这个题目有好多种解决方法。但大致思路都差不多:采用递归算法。

先给出网上比较多的例子:

<?php
$path = ‘F:/TEMP/test’;
function getfiles($path)
{
if(!is_dir($path)) return;
$handle = opendir($path);
while( false !== ($file = readdir($handle)))
{
if($file != ‘.’ && $file!=’..’)
{
$path2= $path.’/’.$file;
if(is_dir($path2))
{
echo ‘ ‘;
echo $file;
getfiles($path2);
}else
{
echo ‘ ‘;
echo $file;
}
}
}
}
print_r( getfiles($path));
echo ‘<HR>’;
function getdir($path)
{
if(!is_dir($path)) return;
$handle = dir($path);
while($file=$handle->read())
{
if($file!=’.’ && $file!=’..’)
{
$path2 = $path.’/’.$file;
if(is_dir($path2))
{
echo $file.”t”;
getdir($path2);
}else
{
echo $file.’ ‘;
}
}
}
}
getdir($path);
echo ‘<HR>’;
function get_dir_scandir($path){
$tree = array();
foreach(scandir($path) as $single){
if($single!=’.’ && $single!=’..’)
{
$path2 = $path.’/’.$single;
if(is_dir($path2))
{
echo $single.”rn”;
get_dir_scandir($path2);
}else
{
echo $single.”rn”;
}
}
}
}
get_dir_scandir($path);
echo ‘
<HR>’;
function get_dir_glob(){
$tree = array();
foreach(glob(‘./curl/*’) as $single){
echo $single.”rn”;
}
}
get_dir_glob();
echo ‘
<HR>’;
function myscandir($path)
{
if(!is_dir($path)) return;
foreach(scandir($path) as $file)
{
if($file!=’.’ && $file!=’..’)
{
$path2= $path.’/’.$file;
if(is_dir($path2))
{
echo $file;
myscandir($path2);
}else
{
echo $file.’ ‘;
}
}
}
}
myscandir($path);
echo ‘<HR>’;
function myglob($path)
{
$path_pattern = $path.’/*’;
foreach(glob($path_pattern) as $file)
{
if(is_dir($file))
{
echo $file;
myscandir($file);
}else
{
echo $file.’ ‘;
}
}
}
myglob($path);

?>

不过,这样的代码显得有些冗余了,有木有更简洁的代码来实现呢~

当然有了,请看下面的例子:

<?php
function my_dir($dir){
$files=array();
if(@$handle=opendir($dir)){//注意这里要加一个@,不然会有warning错误提示:)
while(($file=readdir($handle))!==false){
if($file!=”..” && $file!=”.”){//排除根目录;
if(is_dir($dir.”/”.$file)){//如果是子文件夹,就进行递归
$files[$file]=my_dir($dir.”/”.$file);
}else{//不然就将文件的名字存入数组;
$files[]=$file;
}
}
}
closedir($handle);
return $files;
}
}
//以下是测试
$dir_array=my_dir(‘F:/TEMP/test’);
print_r($dir_array);

?>

上面的例子用PHP创建遍历一个文件夹下所有文件和子文件夹的函数,其中也用到了递归。

不用递归可不可以呢?
回答:可以的。

用非递归方式遍历某个目录下的所有文件,思路主要分三步:

1. 创建一个数组,将要遍历的这个目录放入;(其实就是创建了一个栈)

2. 循环处理这个数组,循环结束的条件是数组为空;

3. 每次循环,处理数组中的一个元素,并将元素删除,如果这个元素是目录,则将目录下所有的子元素加入数组;

按照这种思路写出的代码如下:

<?php
$dir = ‘F:/TEMP/test’;
function scanAll($dir)
{
$list = array();
$list[] = $dir;

while (count($list) > 0)
{
//弹出数组最后一个元素
$file = array_pop($list);

//处理当前文件
echo $file.”rn”;

//如果是目录
if (is_dir($file))
{
$children = scandir($file);
foreach ($children as $child)
{
if ($child !== ‘.’ && $child !== ‘..’)
{
$list[] = $file.’/’.$child;
}
}
}
}
}

?>

这里我并没有认为递归有多大的缺点,事实上很多情况下,用递归来设计还是非常简洁可读的,至于效率问题,除非在递归深度特别大的时候,才会有影响。