array|false glob ( string $pattern [, int $flags = 0 ] )
| 参数 | 描述 |
|---|---|
pattern |
匹配模式,支持shell通配符:* ? [] |
flags |
可选标志位,控制函数行为(详见下表) |
| 常量 | 值 | 描述 |
|---|---|---|
GLOB_MARK |
1 | 在每个返回的项目中加一个斜线(目录标记) |
GLOB_NOSORT |
2 | 按照目录中出现的顺序返回(不排序) |
GLOB_NOCHECK |
4 | 如果没有匹配的文件,返回模式本身 |
GLOB_NOESCAPE |
8 | 反斜线不转义元字符 |
GLOB_BRACE |
16 | 扩展 {a,b,c} 来匹配 'a'、'b' 或 'c' |
GLOB_ONLYDIR |
32 | 仅返回匹配模式的目录项 |
GLOB_ERR |
64 | 在读取错误时停止(如目录不可读),默认情况下忽略错误 |
| 通配符 | 描述 | 示例 | 匹配结果 |
|---|---|---|---|
* |
匹配任意数量的任意字符(包括零个字符) | *.php |
index.php, test.php, .php |
? |
匹配任意单个字符 | file?.txt |
file1.txt, fileA.txt, file_.txt |
[] |
匹配方括号中的任意一个字符 | file[0-9].txt |
file0.txt, file1.txt, file9.txt |
{} |
扩展匹配(需要GLOB_BRACE标志) |
file.{txt,php} |
file.txt, file.php |
** |
递归匹配(PHP 5.3+) | dir/**/*.php |
dir/a.php, dir/sub/b.php |
<?php
// 创建测试文件
touch('test1.php');
touch('test2.php');
touch('image1.jpg');
touch('image2.png');
mkdir('subdir');
touch('subdir/test3.php');
// 基本匹配示例
echo "<h5>1. 匹配所有PHP文件:</h5>";
$phpFiles = glob('*.php');
echo "<pre>" . print_r($phpFiles, true) . "</pre>";
echo "<h5>2. 匹配特定模式的文件:</h5>";
$imageFiles = glob('image*.{jpg,png,gif}', GLOB_BRACE);
echo "<pre>" . print_r($imageFiles, true) . "</pre>";
echo "<h5>3. 匹配单个字符:</h5>";
$testFiles = glob('test?.php');
echo "<pre>" . print_r($testFiles, true) . "</pre>";
echo "<h5>4. 匹配目录(使用GLOB_ONLYDIR):</h5>";
$directories = glob('*', GLOB_ONLYDIR);
echo "<pre>" . print_r($directories, true) . "</pre>";
// 清理测试文件
unlink('test1.php');
unlink('test2.php');
unlink('image1.jpg');
unlink('image2.png');
unlink('subdir/test3.php');
rmdir('subdir');
?>
<?php
// 递归搜索函数(PHP 5.3+支持 ** 通配符)
function recursiveGlob($pattern, $flags = 0) {
// 使用 ** 进行递归匹配(需要 PHP 5.3+)
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$files = glob($pattern, $flags);
return $files !== false ? $files : [];
}
// PHP 5.3以下的替代方案
$files = [];
$parts = explode('/', $pattern);
$dir = $parts[0];
if ($dir === '**') {
// 递归搜索所有子目录
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.'),
RecursiveIteratorIterator::SELF_FIRST
);
$pattern = implode('/', array_slice($parts, 1));
foreach ($iterator as $file) {
if (fnmatch($pattern, $file->getPathname())) {
$files[] = $file->getPathname();
}
}
} else {
$files = glob($pattern, $flags);
}
return $files !== false ? $files : [];
}
// 使用示例
echo "<h5>递归搜索所有PHP文件(包括子目录):</h5>";
// 创建测试目录结构
@mkdir('project');
@mkdir('project/src');
@mkdir('project/tests');
touch('project/index.php');
touch('project/src/utils.php');
touch('project/tests/test.php');
// PHP 5.3+ 方式
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$allPhpFiles = recursiveGlob('project/**/*.php');
echo "<pre>" . print_r($allPhpFiles, true) . "</pre>";
} else {
echo "需要 PHP 5.3+ 支持 ** 递归通配符<br>";
$allPhpFiles = recursiveGlob('**/*.php');
echo "<pre>" . print_r($allPhpFiles, true) . "</pre>";
}
// 清理
unlink('project/index.php');
unlink('project/src/utils.php');
unlink('project/tests/test.php');
rmdir('project/src');
rmdir('project/tests');
rmdir('project');
?>
<?php
class AdvancedFileSearcher {
private $rootPath;
private $patterns = [];
private $excludePatterns = [];
private $flags = 0;
public function __construct($rootPath = '.') {
$this->rootPath = rtrim($rootPath, '/\\');
}
/**
* 添加搜索模式
*/
public function addPattern($pattern) {
$this->patterns[] = $pattern;
return $this;
}
/**
* 添加排除模式
*/
public function excludePattern($pattern) {
$this->excludePatterns[] = $pattern;
return $this;
}
/**
* 设置标志位
*/
public function setFlags($flags) {
$this->flags = $flags;
return $this;
}
/**
* 执行搜索
*/
public function search() {
$results = [];
foreach ($this->patterns as $pattern) {
$fullPattern = $this->rootPath . '/' . ltrim($pattern, '/');
$matches = glob($fullPattern, $this->flags);
if ($matches !== false) {
foreach ($matches as $file) {
// 检查是否应该排除
if (!$this->shouldExclude($file)) {
$results[] = $file;
}
}
}
}
// 去重并排序
$results = array_unique($results);
if (!($this->flags & GLOB_NOSORT)) {
sort($results);
}
return $results;
}
/**
* 递归搜索(支持子目录)
*/
public function searchRecursive() {
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
throw new Exception("递归搜索需要 PHP 5.3+");
}
$results = [];
foreach ($this->patterns as $pattern) {
// 将模式转换为递归模式
$recursivePattern = $this->convertToRecursivePattern($pattern);
$fullPattern = $this->rootPath . '/' . ltrim($recursivePattern, '/');
$matches = glob($fullPattern, $this->flags);
if ($matches !== false) {
foreach ($matches as $file) {
if (!$this->shouldExclude($file)) {
$results[] = $file;
}
}
}
}
$results = array_unique($results);
if (!($this->flags & GLOB_NOSORT)) {
sort($results);
}
return $results;
}
/**
* 转换为递归模式
*/
private function convertToRecursivePattern($pattern) {
$dir = dirname($pattern);
$file = basename($pattern);
if ($dir === '.') {
return '**/' . $file;
}
return $dir . '/**/' . $file;
}
/**
* 检查是否应该排除文件
*/
private function shouldExclude($file) {
foreach ($this->excludePatterns as $pattern) {
$fullPattern = $this->rootPath . '/' . ltrim($pattern, '/');
if (fnmatch($fullPattern, $file)) {
return true;
}
}
return false;
}
/**
* 按文件类型过滤
*/
public function filterByType($type = 'file') {
$results = $this->search();
$filtered = [];
foreach ($results as $file) {
if ($type === 'file' && is_file($file)) {
$filtered[] = $file;
} elseif ($type === 'dir' && is_dir($file)) {
$filtered[] = $file;
}
}
return $filtered;
}
}
// 使用示例
try {
// 创建测试文件结构
@mkdir('project');
@mkdir('project/src');
@mkdir('project/tests');
@mkdir('project/tmp');
touch('project/index.php');
touch('project/composer.json');
touch('project/src/Controller.php');
touch('project/src/Model.php');
touch('project/tests/TestController.php');
touch('project/tmp/cache.tmp');
echo "<h5>高级文件搜索示例:</h5>";
// 创建搜索器
$searcher = new AdvancedFileSearcher('project');
// 搜索所有PHP文件,排除测试目录
$searcher
->addPattern('*.php')
->addPattern('src/*.php')
->excludePattern('tests/*');
$phpFiles = $searcher->searchRecursive();
echo "<h6>所有PHP文件(排除tests目录):</h6>";
echo "<pre>" . print_r($phpFiles, true) . "</pre>";
// 搜索所有JSON文件
$searcher2 = new AdvancedFileSearcher('project');
$jsonFiles = $searcher2->addPattern('*.json')->search();
echo "<h6>所有JSON文件:</h6>";
echo "<pre>" . print_r($jsonFiles, true) . "</pre>";
// 只搜索目录
$searcher3 = new AdvancedFileSearcher('project');
$directories = $searcher3
->addPattern('*')
->setFlags(GLOB_ONLYDIR)
->search();
echo "<h6>所有子目录:</h6>";
echo "<pre>" . print_r($directories, true) . "</pre>";
// 清理
unlink('project/index.php');
unlink('project/composer.json');
unlink('project/src/Controller.php');
unlink('project/src/Model.php');
unlink('project/tests/TestController.php');
unlink('project/tmp/cache.tmp');
rmdir('project/src');
rmdir('project/tests');
rmdir('project/tmp');
rmdir('project');
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>
opendir()和readdir()循环**递归通配符,旧版本需要自己实现递归*不会匹配以点(.)开头的文件,需要使用.*GLOB_NOSORT保持原始顺序GLOB_ERR在错误时停止| 特性 | glob() | scandir() |
|---|---|---|
| 功能 | 模式匹配文件路径 | 列出目录中的所有文件和目录 |
| 模式支持 | 支持通配符 * ? [] {} | 不支持模式匹配 |
| 返回结果 | 只返回匹配的项目 | 返回所有项目(包括 . 和 ..) |
| 性能 | 可能较慢(需要模式匹配) | 通常较快(简单列出) |
| 使用场景 | 搜索特定类型的文件 | 遍历目录中的所有项目 |
scandir() - 列出指定路径中的文件和目录opendir() - 打开目录句柄readdir() - 从目录句柄中读取条目fnmatch() - 用模式匹配文件名is_file() - 判断是否是文件is_dir() - 判断是否是目录RecursiveDirectoryIterator - 递归目录迭代器搜索特定类型的文件,如所有图片、文档或源代码文件。
在项目中查找所有配置文件、模板文件或资源文件。
查找特定时间段的日志文件进行分析和处理。
对匹配特定模式的文件执行批量操作,如重命名、删除或处理。