我想使用 PHP 读取 .gitignore 配置忽略的所有文件和路径。就像 git 一样。
可以重复读取目录,并对要过滤的每个文件使用正则表达式。但是,如果路径包含太多文件,则效果不佳。
有什么好的和最有效的方法来读取被 .gitignore 忽略的目标文件和路径?
您需要分几个步骤进行:
1 - 查找 .gitignore 文件
每个文件夹可以有一个,所以不要假设只有一个。
子模块有一个指向主 .git 文件夹的 .git 链接,所以也要小心不要过早停止。
它会像这样:
function find_gitignore_files($dir) {
$files = array();
while (true) {
$file = "$dir/.gitignore";
if (is_file($file)) $files[] = $file;
if (is_dir("$dir/.git") && !is_link("$dir/.git")) break; # stop here
if (dirname($dir) === '.') break; # and here
$dir = dirname($dir);
}
return $files;
}
2 - 解析每个 .gitignore 文件
您需要忽略注释,注意否定运算符(!
),并注意globs。
这个是,给予或接受,将像这样:
function parse_git_ignore_file($file) { # $file = '/absolute/path/to/.gitignore'
$dir = dirname($file);
$matches = array();
$lines = file($file);
foreach ($lines as $line) {
$line = trim($line);
if ($line === '') continue; # empty line
if (substr($line, 0, 1) == '#') continue; # a comment
if (substr($line, 0, 1) == '!') { # negated glob
$line = substr($line, 1);
$files = array_diff(glob("$dir/*"), glob("$dir/$line"));
} else { # normal glob
$files = glob("$dir/$line");
}
$matches = array_merge($matches, $files);
}
return $matches;
}
(注意:以上都未经测试,但它们应该会让你朝着正确的方向前进。
只是一个疯狂的想法:如果你依靠 Git 为你提供被忽略文件的模式,为什么不依靠它来提供包含/忽略文件的列表?只需发出如下命令:
- 所有跟踪文件的
git ls-files
-
git clean -ndX
或git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore
所有忽略的文件
查看哪个 Git 命令为您提供最佳输出,然后遍历路径文件。
请注意:执行外部命令时,请采取所有必要的预防措施!
来源:
- 在 git 中显示忽略的文件
- 列出本地 git 存储库中的文件?
我使用这个函数来读取整个路径,效果很好
function read_dir($dir)
{
$files = array();
$dir = preg_replace('~'/+~','/',$dir . '/');
$all = scandir($dir);
foreach($all as $path):
if($path !== '.' && $path !== '..'):
$path = $dir . '/' . $path;
$path = preg_replace('~'/+~','/',$path);
$path = realpath($path);
if(is_dir($path)):
$files = array_merge($files, read_dir($path));
endif;
$files[] = preg_replace('~/+~i','/',$path);
endif;
endforeach;
return $files;
}
更新:您可以在上述功能上使用preg_grep,如下所示
$files = preg_grep('~'.gitignore'b~i', array_values(read_dir($path)));
gitignore 中的条目大多是 glob 模式。 您可以使用 PHP 的 file
函数读取 .gitignore 的每一行,忽略空行和以 #
开头的行,然后使用 PHP glob
函数读取模式 (http://php.net/manual/en/function.glob.php)
您可以从.gitignore
文件中获取要忽略的文件数组并对其进行检查。为此,您需要读取文件并使用glob
函数匹配文件。
首先,获取文件的内容:
$contents = file_get_contents($pathToGitIgnoreFile);
$path = dirname(realpath($pathToGitIgnoreFile));
您还可以使用 .gitignore
文件的目录来匹配与 gitignore 位于同一目录中的文件。
接下来,我们需要将内容拆分为单独的规则。规则从文件中自己的行开始。以井号 ( #
) 开头的行是注释,因此我们可以使用正则表达式来查找不是注释的非空行:
$rules = array();
preg_match_all('/[''A''v]([^#''v]''V*)[''z''v]?/', $contents, $rules);
$rules = $rules[1];
然后,您所要做的就是遍历规则并使用glob
创建一个要忽略的文件名数组:
$files = array();
foreach ($rules as $rule)
{
if (strpos($rule, '!') === 0) // negative rule
$files = array_diff($files, glob($path . DIRECTORY_SEPARATOR . substr($rule, 1)));
else
$files = array_merge($files, glob($path . DIRECTORY_SEPARATOR . $rule));
}
$files = array_unique($files);
我没有测试此代码,因此如果它对您不起作用,请在下面发表评论。
SPL(标准PHP库)包含该作业的一些迭代器。我将示例限制为过滤掉名称中以"."开头的所有目录或文件。
.gitignore 的规则非常复杂,解析条目并构建一组规则将远远超出示例的范围。
$directory = __DIR__;
$filtered = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator($directory),
function ($fileInfo, $key, $iterator) {
// only accept entries that do not start with an .
return substr($fileInfo->getFilename(), 0, 1) != '.';
}
)
);
foreach ($filtered as $fileInfo) {
echo (string)$fileInfo, "'n";
}