本文目录导读:

我来为你提供几种PHP目录遍历递归实现的方法:
递归函数实现
<?php
/**
* 递归遍历目录
* @param string $dir 目录路径
* @param array &$result 存储结果
* @return array
*/
function scanDirRecursive($dir, &$result = []) {
// 检查目录是否存在
if (!is_dir($dir)) {
return $result;
}
// 扫描目录
$files = scandir($dir);
foreach ($files as $file) {
// 跳过 . 和 ..
if ($file == '.' || $file == '..') {
continue;
}
// 完整路径
$path = $dir . '/' . $file;
// 如果是目录,递归遍历
if (is_dir($path)) {
$result[] = [
'type' => 'dir',
'name' => $file,
'path' => $path,
'children' => []
];
// 递归
$index = count($result) - 1;
scanDirRecursive($path, $result[$index]['children']);
} else {
// 文件
$result[] = [
'type' => 'file',
'name' => $file,
'path' => $path,
'size' => filesize($path),
'ext' => pathinfo($path, PATHINFO_EXTENSION)
];
}
}
return $result;
}
// 使用方法
$files = scanDirRecursive('/path/to/directory');
echo "<pre>";
print_r($files);
echo "</pre>";
?>
使用RecursiveIteratorIterator
<?php
/**
* 使用SPL递归迭代器
* @param string $dir 目录路径
* @return array
*/
function scanDirWithIterator($dir) {
$result = [];
if (!is_dir($dir)) {
return $result;
}
// 创建递归目录迭代器
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir,
FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS
),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $item) {
$entry = [
'name' => $item->getFilename(),
'path' => $item->getPathname(),
'type' => $item->isDir() ? 'dir' : 'file'
];
// 如果是文件,添加文件信息
if ($item->isFile()) {
$entry['size'] = $item->getSize();
$entry['ext'] = $item->getExtension();
}
$result[] = $entry;
}
return $result;
}
// 使用方法
$files = scanDirWithIterator('/path/to/directory');
?>
带格式化的树形结构
<?php
/**
* 获取目录树形结构
* @param string $dir 目录路径
* @param int $level 层级(内部使用)
* @return string
*/
function getDirectoryTree($dir, $level = 0) {
static $tree = '';
if (!is_dir($dir)) {
return $tree;
}
// 获取目录内容
$items = scandir($dir);
foreach ($items as $item) {
if ($item == '.' || $item == '..') {
continue;
}
$path = $dir . '/' . $item;
$indent = str_repeat(' ', $level);
if (is_dir($path)) {
$tree .= $indent . "📁 {$item}/\n";
getDirectoryTree($path, $level + 1);
} else {
$size = formatFileSize(filesize($path));
$tree .= $indent . "📄 {$item} ({$size})\n";
}
}
return $tree;
}
/**
* 格式化文件大小
* @param int $bytes
* @return string
*/
function formatFileSize($bytes) {
if ($bytes >= 1073741824) {
return round($bytes / 1073741824, 2) . ' GB';
} elseif ($bytes >= 1048576) {
return round($bytes / 1048576, 2) . ' MB';
} elseif ($bytes >= 1024) {
return round($bytes / 1024, 2) . ' KB';
} else {
return $bytes . ' B';
}
}
// 使用方法
echo getDirectoryTree('/path/to/directory');
?>
过滤特定文件的遍历
<?php
/**
* 递归遍历并过滤文件
* @param string $dir 目录
* @param array $extensions 允许的文件扩展名
* @param bool $includeHidden 是否包含隐藏文件
* @return array
*/
function scanDirWithFilter($dir, $extensions = [], $includeHidden = false) {
$result = [];
if (!is_dir($dir)) {
return $result;
}
$items = scandir($dir);
foreach ($items as $item) {
// 过滤隐藏文件
if (!$includeHidden && substr($item, 0, 1) == '.') {
continue;
}
if ($item == '.' || $item == '..') {
continue;
}
$path = $dir . '/' . $item;
if (is_dir($path)) {
// 递归处理子目录
$subFiles = scanDirWithFilter($path, $extensions, $includeHidden);
if (!empty($subFiles)) {
$result[$item] = $subFiles;
}
} else {
// 文件扩展名过滤
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (empty($extensions) || in_array($ext, $extensions)) {
$result[] = $path;
}
}
}
return $result;
}
// 使用示例:只获取php和html文件
$files = scanDirWithFilter('/path/to/directory', ['php', 'html'], true);
print_r($files);
?>
异步/回调函数实现
<?php
/**
* 使用回调函数处理每个文件
* @param string $dir 目录
* @param callable $callback 回调函数
* @return void
*/
function traverseDirectory($dir, $callback) {
if (!is_dir($dir)) {
return;
}
$items = scandir($dir);
foreach ($items as $item) {
if ($item == '.' || $item == '..') {
continue;
}
$path = $dir . '/' . $item;
if (is_dir($path)) {
// 调用回调函数处理目录
call_user_func($callback, $path, 'dir');
// 递归处理子目录
traverseDirectory($path, $callback);
} else {
// 调用回调函数处理文件
call_user_func($callback, $path, 'file');
}
}
}
// 使用示例
$totalSize = 0;
$fileCount = 0;
traverseDirectory('/path/to/directory', function($path, $type) use (&$totalSize, &$fileCount) {
if ($type == 'file') {
$totalSize += filesize($path);
$fileCount++;
echo "文件: {$path} (" . formatFileSize(filesize($path)) . ")\n";
} else {
echo "目录: {$path}\n";
}
});
echo "\n统计信息:\n";
echo "文件总数: {$fileCount}\n";
echo "总大小: " . formatFileSize($totalSize) . "\n";
?>
性能优化建议
<?php
/**
* 高性能递归遍历(推荐)
*/
function scanDirEfficient($dir) {
$result = [];
// 使用FilesystemIterator性能更好
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($dir,
FilesystemIterator::SKIP_DOTS | FilesystemIterator::QUERY_WHERE
)
);
foreach ($iterator as $file) {
if ($file->isFile()) {
$result[] = [
'path' => $file->getPathname(),
'filename' => $file->getFilename(),
'size' => $file->getSize(),
'modified' => date('Y-m-d H:i:s', $file->getMTime())
];
}
}
return $result;
}
?>
选择哪种方法取决于你的具体需求:
- 方法一:适合需要树形结构的场景
- 方法二:性能好,适合简单遍历
- 方法三:适合可视化展示
- 方法四:适合需要过滤的场景
- 方法五:适合需要实时处理的场景
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播