准备好用于常见用例的复制和粘贴功能,上面一个答案的改进/扩展版本:
function getDirContents(string $dir, int $onlyFiles = 0, string $excludeRegex = '~/\.git/~', int $maxDepth = -1): array {
$results = [];
$scanAll = scandir($dir);
sort($scanAll);
$scanDirs = []; $scanFiles = [];
foreach($scanAll as $fName){
if ($fName === '.' || $fName === '..') { continue; }
$fPath = str_replace(DIRECTORY_SEPARATOR, '/', realpath($dir . '/' . $fName));
if (strlen($excludeRegex) > 0 && preg_match($excludeRegex, $fPath . (is_dir($fPath) ? '/' : ''))) { continue; }
if (is_dir($fPath)) {
$scanDirs[] = $fPath;
} elseif ($onlyFiles >= 0) {
$scanFiles[] = $fPath;
}
}
foreach ($scanDirs as $pDir) {
if ($onlyFiles <= 0) {
$results[] = $pDir;
}
if ($maxDepth !== 0) {
foreach (getDirContents($pDir, $onlyFiles, $excludeRegex, $maxDepth - 1) as $p) {
$results[] = $p;
}
}
}
foreach ($scanFiles as $p) {
$results[] = $p;
}
return $results;
}
如果您需要相对路径:
function updateKeysWithRelPath(array $paths, string $baseDir, bool $allowBaseDirPath = false): array {
$results = [];
$regex = '~^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($baseDir)), '~') . '(?:/|$)~s';
$regex = preg_replace('~/~', '/(?:(?!\.\.?/)(?:(?!/).)+/\.\.(?:/|$))?(?:\.(?:/|$))*', $regex);
if (DIRECTORY_SEPARATOR === '\\') {
$regex = preg_replace('~/~', '[/\\\\\\\\]', $regex) . 'i';
}
foreach ($paths as $p) {
$rel = preg_replace($regex, '', $p, 1);
if ($rel === $p) {
throw new \Exception('Path relativize failed, path "' . $p . '" is not within basedir "' . $baseDir . '".');
} elseif ($rel === '') {
if (!$allowBaseDirPath) {
throw new \Exception('Path relativize failed, basedir path "' . $p . '" not allowed.');
} else {
$results[$rel] = './';
}
} else {
$results[$rel] = $p;
}
}
return $results;
}
function getDirContentsWithRelKeys(string $dir, int $onlyFiles = 0, string $excludeRegex = '~/\.git/~', int $maxDepth = -1): array {
return updateKeysWithRelPath(getDirContents($dir, $onlyFiles, $excludeRegex, $maxDepth), $dir);
}
此版本解决/改进了:
realpath
当PHPopen_basedir
不覆盖..
目录时发出警告。
- 不对结果数组使用引用
- 允许排除目录和文件
- 仅允许列出文件/目录
- 允许限制搜索深度
- 它总是先对目录进行排序(因此可以以相反的顺序删除/清空目录)
- 允许使用相对键获取路径
- 针对数十万甚至数百万个文件进行了优化
- 在评论中写更多:)
例子:
$onlyPhpFilesExcludeRegex = '~/\.git/|(?<!/|\.php)$|^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath(__FILE__)), '~') . '$~is';
$phpFiles = getDirContents(__DIR__, 1, $onlyPhpFilesExcludeRegex);
print_r($phpFiles);
$phpFiles = getDirContentsWithRelKeys(__DIR__, 1, $onlyPhpFilesExcludeRegex);
print_r($phpFiles);
'~/\.git/|^(?!.*/(|' . '[^/]+_mails/en/[^/]+\.(?:html|txt)' . ')$)~is'
RecursiveDirectoryIterator