fix: 优化系统目录扫描

This commit is contained in:
邹景立 2024-09-01 00:33:36 +08:00
parent 0cf4a12711
commit 9c6b1c430e

View File

@ -45,21 +45,20 @@ class ToolsExtend
$todir = rtrim($todir, '\\/') . DIRECTORY_SEPARATOR; $todir = rtrim($todir, '\\/') . DIRECTORY_SEPARATOR;
// 扫描目录文件 // 扫描目录文件
if (empty($files) && is_dir($frdir)) { if (empty($files) && is_dir($frdir)) {
$files = static::findFilesArray($frdir, static function (SplFileInfo $info) { $filter = function (SplFileInfo $info) {
return substr($info->getBasename(), 0, 1) !== '.'; return $info->getBasename()[0] !== '.';
}, static function (SplFileInfo $info) { };
return substr($info->getBasename(), 0, 1) !== '.'; $files = static::findFilesArray($frdir, $filter, $filter);
});
} }
// 复制文件列表 // 复制文件列表
foreach ($files as $target) { foreach ($files as $target) {
if ($force || !is_file($todir . $target)) { [$fromPath, $destPath] = [$frdir . $target, $todir . $target];
$dir = dirname($todir . $target); if ($force || !is_file($destPath)) {
is_dir($dir) or mkdir($dir, 0777, true); is_dir($dir = dirname($destPath)) || mkdir($dir, 0777, true);
copy($frdir . $target, $todir . $target); copy($fromPath, $destPath);
} }
// 删除来源文件 // 删除来源文件
$remove && unlink($frdir . $target); $remove && unlink($fromPath);
} }
// 删除来源目录 // 删除来源目录
$remove && static::removeEmptyDirectory($frdir); $remove && static::removeEmptyDirectory($frdir);
@ -76,51 +75,45 @@ class ToolsExtend
public static function scanDirectory(string $path, string $filterExt = '', bool $shortPath = true): array public static function scanDirectory(string $path, string $filterExt = '', bool $shortPath = true): array
{ {
return static::findFilesArray($path, static function (SplFileInfo $info) use ($filterExt) { return static::findFilesArray($path, static function (SplFileInfo $info) use ($filterExt) {
return empty($filterExt) || $info->getExtension() === $filterExt; return !$filterExt || $info->getExtension() === $filterExt;
}, static function (SplFileInfo $info) { }, static function (SplFileInfo $info) {
return substr($info->getBasename(), 0, 1) !== '.'; return $info->getBasename()[0] !== '.';
}, $shortPath); }, $shortPath);
} }
/** /**
* 扫描指定目录 * 扫描指定目录并返回文件路径数组
* @param string $path * @param string $path 要扫描的目录路径
* @param ?Closure $filterFile * @param ?Closure $filterFile 用于过滤文件的闭包
* @param ?Closure $filterPath * @param ?Closure $filterPath 用于过滤目录的闭包
* @param boolean $shortPath * @param boolean $shortPath 是否返回相对于给定路径的短路径
* @return array * @return array 包含文件路径的数组
*/ */
public static function findFilesArray(string $path, ?Closure $filterFile = null, ?Closure $filterPath = null, bool $shortPath = true): array public static function findFilesArray(string $path, ?Closure $filterFile = null, ?Closure $filterPath = null, bool $shortPath = true): array
{ {
$items = []; $pathLength = $shortPath ? strlen(realpath($path)) + 1 : 0;
if (file_exists($path)) { return file_exists($path) ? array_map(function ($file) use ($shortPath, $pathLength) {
$files = static::findFilesYield($path, $filterFile, $filterPath); return $shortPath ? substr($file->getRealPath(), $pathLength) : $file->getRealPath();
foreach ($files as $file) $items[] = $file->getRealPath(); }, iterator_to_array(static::findFilesYield($path, $filterFile, $filterPath))) : [];
if ($shortPath && ($offset = strlen(realpath($path)) + 1)) {
foreach ($items as &$item) $item = substr($item, $offset);
}
}
return $items;
} }
/** /**
* 扫描指定目录 * 递归扫描指定目录,返回文件或目录的 SplFileInfo 对象。
* @param string $path * @param string $path 目录路径。
* @param \Closure|null $filterFile * @param \Closure|null $filterFile 文件过滤器闭包,返回 true 表示文件被接受。
* @param \Closure|null $filterPath * @param \Closure|null $filterPath 目录过滤器闭包,返回 true 表示目录被接受。
* @param boolean $fullDirectory * @param boolean $fullDirectory 是否包含目录本身在结果中。
* @return \Generator|\SplFileInfo[] * @return \Generator 返回 SplFileInfo 对象的生成器。
*/ */
public static function findFilesYield(string $path, ?Closure $filterFile = null, ?Closure $filterPath = null, bool $fullDirectory = false): Generator public static function findFilesYield(string $path, ?Closure $filterFile = null, ?Closure $filterPath = null, bool $fullDirectory = false): Generator
{ {
if (file_exists($path)) { if (!file_exists($path)) return;
$items = is_file($path) ? [new SplFileInfo($path)] : new FilesystemIterator($path); foreach (is_file($path) ? [new SplFileInfo($path)] : new FilesystemIterator($path) as $item) {
foreach ($items as $item) if ($item->isDir() && !$item->isLink()) { $isDir = $item->isDir() && !$item->isLink();
if (is_null($filterPath) || $filterPath($item)) { if ($isDir && ($filterPath === null || $filterPath($item))) {
yield from static::findFilesYield($item->getPathname(), $filterFile, $filterPath, $fullDirectory); yield from static::findFilesYield($item->getPathname(), $filterFile, $filterPath, $fullDirectory);
} if ($fullDirectory) yield $item;
$fullDirectory && yield $item; } elseif (!$isDir && ($filterFile === null || $filterFile($item))) {
} elseif (is_null($filterFile) || $filterFile($item)) {
yield $item; yield $item;
} }
} }