文件遍历器
每种 Greph 模式(文本、AST、重写、索引文本、索引 AST、缓存 AST、rg 包装器、sg 包装器)都会先遍历文件树并生成一个 Greph\Walker\FileList。遍历器由所有模式共享,因此各处使用相同的标志和行为。
默认行为
遍历器开箱即用时会:
- 递归进入所请求路径下的每个目录。
- 在每一层遵循
.gitignore和.grephignore规则,包括嵌套覆盖和否定规则。 - 跳过
.git目录。 - 跳过隐藏文件和目录(名称以
.开头的内容)。 - 跳过二进制文件(通过文件前 512 个字节中的空字节检测)。
- 跳过大于 10 MiB 的文件。
- 不跟随符号链接。
覆盖标志
| 标志 | 效果 |
|---|---|
--no-ignore |
停止遵循 .gitignore 和 .grephignore |
--hidden |
包含隐藏文件和目录 |
--type NAME |
仅包含与指定类型别名匹配的文件 |
--type-not NAME |
排除与指定类型别名匹配的文件 |
--glob GLOB |
仅包含路径与 GLOB 匹配的文件。可重复指定。 |
这些选项也通过 Greph\Walker\WalkOptions 提供,以便以编程方式使用。
use Greph\Greph;
use Greph\Walker\FileTypeFilter;
use Greph\Walker\WalkOptions;
$files = Greph::walk('src', new WalkOptions(
respectIgnore: false,
includeHidden: true,
fileTypeFilter: new FileTypeFilter(['php']),
globPatterns: ['src/**/*.php'],
));
文件类型别名
Greph 附带一组小型命名文件类型。每个别名都对应一个扩展名列表:
| 别名 | 扩展名 |
|---|---|
css |
css、sass、scss |
html |
htm、html、phtml |
js |
cjs、js、mjs |
json |
json |
md |
markdown、md |
php |
inc、php、php3、php4、php5、php7、php8、phpt、phtml |
txt |
txt |
ts |
ts、tsx |
xml |
xml |
yaml |
yaml、yml |
完整列表见 Greph\Walker\FileTypeFilter::TYPE_MAP。
.gitignore 语义
Greph 使用纯 PHP 实现 gitignore 匹配。其语义与 git check-ignore 保持一致:
- 模式相对于其所在目录进行求值。
- 嵌套的
.gitignore文件会覆盖父级规则。 - 否定规则(
!pattern)会重新包含先前排除的路径。 - 末尾的
/将模式限定为目录。 - 开头的
/将模式锚定到.gitignore所在目录。 **可匹配任意数量的路径段。
.grephignore 使用相同语法,并叠加在 .gitignore 之上。你可以在此添加不想纳入版本控制的工具专属排除规则。
实现位于 Greph\Walker\GitignoreFilter。
二进制文件检测
遍历器会检查每个文件前 512 个字节中是否含有空字节。如果存在空字节,该文件就会被视为二进制文件并跳过。这能捕获常见情况:仓库在已编入索引的目录中包含图像、归档或编译产物。
若仍要搜索二进制文件,请在相关的 Options 对象上设置 skipBinaryFiles: false。CLI 目前没有提供此标志;请使用 facade。
符号链接
默认情况下不会跟随符号链接。设置 followSymlinks: true(或在 rg 包装器上传入 -L / --follow)即可跟随符号链接。遍历器会跟踪已访问的目录,因此符号链接循环不会导致无限递归。
最大文件大小
大于 maxFileSizeBytes(默认 10 MiB)的文件会被跳过。这可以避免意外将 1 GB 的日志文件读入内存,从而保护扫描过程。需要处理更大的输入时,可在 Options 对象上调整此限制。
为什么要自定义遍历器
Greph 可以依赖 glob() 或 RecursiveDirectoryIterator,但两者都没有实现 gitignore 语义,也都无法识别 .grephignore,并且都无法与工作池顺畅集成。只编写一次遍历器并在各模式间共享,也意味着每种模式应用的过滤规则完全相同,这对基于 oracle 的测试策略至关重要:要与 grep、ripgrep 和 ast-grep 比较,唯一办法是遍历这些工具所遍历的同一组文件。