PHP实现文件夹遍历与大小计算的核心代码示例
本文将详细解析如何使用PHP原生函数实现文件夹的遍历输出与总大小计算。内容涵盖递归遍历目录树的逻辑构建、避免死循环的路径过滤技巧,以及将字节数转换为KB/MB/GB的单位显示函数,帮助开发者快速掌握文件系统操作的核心代码。
PHP文件夹操作的两种核心场景
在进行后端开发或服务器管理时,经常需要读取服务器上的文件信息。主要涉及两个需求:一是将目录下的所有文件和子目录以列表形式呈现(遍历);二是统计一个目录下所有文件的总体积(计算大小)。这两个操作通常都依赖于递归思想,因为文件夹内可能包含无限的子文件夹层级。
完整递归遍历目录并打印文件树
要实现类似Windows资源管理器那样的目录树效果,需要使用递归函数不断深入子目录。以下代码不仅遍历文件,还根据目录深度输出缩进,并在最后统计文件总数。
第1步:理解遍历函数的关键逻辑
目的: 获取指定路径下所有文件和文件夹的名称,并按层级缩进显示。
入口: scan_dir 函数接收目录名和缩进标识参数。
动作: 使用 opendir 打开句柄,通过 readdir 循环读取条目。注意必须剔除当前路径 . 和上级路径 ..,否则会导致无限递归并耗尽内存。
<?php
//功能:遍历并打印指定目录下所有文件
function scan_dir($dir_name,$dir_flag=1) {
static $FILE_COUNT=1; //记录文件数目 初值为1 目录名称不记
$FILE_COUNT--; //每调用一次scan_dir()函数自减1
@$dir_handle=opendir($dir_name); //抑制错误信息显示 便于自定义错误显示
if(!$dir_handle)
die("目录打开错误!");
while(false!==($filename=readdir($dir_handle))) //文件名为‘0'时,readdir返回 FALSE,判断返回值是否不全等
{
$flag=$dir_flag; //古怪的 is_dir($filename) ! $filename这个路径必须能够寻到!当$filename不存在或者不是目录时返回false
if($filename!='.'&&$filename!='..')
{
$FILE_COUNT++; //不记录当前路径和上一级路径
while($flag>0&&--$flag) //负数仍为真
echo ' ';
if(is_dir($dir_name.$filename)) //判断 是否为一个目录
{
echo '<strong>'."<a href=".$dir_name.$filename.">".$filename."</a></strong><br>";
scan_dir($dir_name.$filename.'/',$dir_flag+1); //$dir_flag标志目录树层次
}
else
{
echo "<a href=".$dir_name.$filename.">".$filename."</a><br>";
}
}
}
closedir($dir_handle); //关闭目录句柄
echo "文件总数:".$FILE_COUNT.'<br>';
}
scan_dir('D:/AppServ/www/mytest/shopping/payment/');
/*总结:
1,关于路径 目录的路径末尾都加上 '/' 以便后面与文件名字符串连接 形成新的 路径字符串
2,目录遍历 这是一个关于树的问题
3,is_dir()函数第一个参数必须是一个能够识别的PATH否则会因目录不存在而返回一个false容易误解
得出 “这不是一个目录”的错误结论 形成逻辑上的错误
4,注意当前路径'.'和上一级路径'..'的剔除 否则 在递归环节造成死循环 直至内存耗尽出错。
5,dir_flag这个变量是记录树的深度 以便于目录分级分层输出 */
/*不足
1,输出排版不完善
2,逻辑与表示层混乱 不分明 大忌!
3,面向过程
*/
注意事项: 上述代码将HTML输出与逻辑处理混合在一起。在实际工程化应用中,建议将数据收集到数组后,再通过模板引擎渲染,以实现逻辑与视图分离。
单目录简单列出内容
如果不需要递归子目录,仅需列出当前一层的内容,可以使用更简单的非递归写法。这适用于生成简单的文件下载列表。
第2步:实现单层文件列表
重点: 同样需要忽略 ., .. 以及系统生成的隐藏文件如 Thumbs.db(Windows特有)。
// 列出目录内容 $dir 不要加 '/'
function list_files($dir)
{
if(is_dir($dir))
{
if($handle = opendir($dir))
{
while(($file = readdir($handle)) !== false)
{
if($file != "." && $file != ".." && $file != "Thumbs.db")
{
echo '<a href="'.$dir.'/'.$file.'">'.$file.'</a><br>'."\n";
}
}
closedir($handle);
}
}
}
list_files('D:/AppServ/www/mytest/shopping/payment');
递归计算文件夹总大小
计算目录大小是另一个高频场景,常用于清理空间预警或磁盘配额检查。核心思路是对每个子目录递归调用自身累加大小,对普通文件则调用 filesize()。
第3步:执行递归大小累加
参数: 传入完整的绝对路径。
步骤: 打开目录 -> 循环读取 -> 判断是否为目录 -> 是则递归 + 否则累加 filesize -> 关闭句柄。
<?php
function getDirSize($dir)
{
$handle = opendir($dir);
while (false!==($FolderOrFile = readdir($handle)))
{
if($FolderOrFile != "." && $FolderOrFile != "..")
{
if(is_dir("$dir/$FolderOrFile"))
{
$sizeResult += getDirSize("$dir/$FolderOrFile");
}
else
{
$sizeResult += filesize("$dir/$FolderOrFile");
}
}
}
closedir($handle);
return $sizeResult;
}
//单位自动转换函数
function getRealSize($size)
{
$kb = 1024; //Kilobyte
$mb = 1024 * $kb; //Megabyte
$gb = 1024 * $mb; //Gigabyte
$tb = 1024 * $gb; //Terabyte
if($size < $kb)
{
return $size." B";
}
else if($size < $mb)
{
return round($size/$kb,2)." KB";
}
else if($size < $gb)
{
return round($size/$mb,2)." MB";
}
else if($size < $tb)
{
return round($size/$tb,2)." GB";
}
else
{
return round($size/$tb,2)." TB";
}
}
echo getRealSize(getDirSize('D:/AppServ/www/mytest/'));
另一种紧凑写法如下,适合快速集成:
// get byte
function dirsize($dir)
{
$handle=opendir($dir);
$size = 0;
while ( $file=readdir($handle) )
{
if ( ( $file == "." ) || ( $file == ".." ) ) continue;
if ( is_dir("$dir/$file") )
$size += dirsize("$dir/$file");
else
$size += filesize("$dir/$file");
}
closedir($handle);
return $size;
}
$big=dirsize(dirname($_SERVER['SCRIPT_FILENAME'])."/");
echo '('.$big.' bytes)';
常见问题与排错指南
在使用PHP文件系统函数时,以下几点容易导致BUG,需特别注意:
- 路径斜杠问题: 拼接路径时务必确认父目录末尾是否有
/,例如$dir . '/' . $file或确保入参自带尾部斜杠,否则可能导致is_dir判断失败。 - 权限拒绝: 如果脚本没有读取该目录的权限,
opendir可能返回false或触发警告。生产环境中建议使用 @ 符号抑制错误或显式检查返回值。 - 大量文件性能: 对于包含成千上万个小文件的巨大目录,递归可能会导致栈溢出或响应超时。此时应考虑使用
glob或迭代器模式替代深层递归。
以上就是PHP实现文件夹遍历与大小计算的详细内容,更多关于PHP目录操作技术的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













