嗯,最好的解析方式.gitignore
文件(以及 Git 使用的其他文件,例如$GIT_DIR/info/exclude
) 就是让 Git 为你做这件事。 :-) (在你的情况下,事实上,大多数情况下,这确实涉及执行 git 子进程。)
git check-ignore
The git check-ignore命令可用于检测哪些文件被忽略以及原因。这--non-matching
选项使其告诉您有关未被忽略的文件的信息,但由于它仍然以特殊格式告诉您有关被忽略的文件的信息,因此您需要做一些进一步的工作才能获得一个简单的列表不可忽略的文件。这个 Bourne shell 函数可以解决这个问题:
find_nonignored() {
find . -path ./.git -prune -o -print \
| git check-ignore --verbose --non-matching --stdin \
| sed -n -e 's,\t./,\t,' -e 's,^::\t*,,p' \
}
怎么运行的
The find
命令查找当前工作目录及其下的所有文件,该目录应该位于您要过滤的树中的某个位置。我们排除了顶级.git
输出中的子目录及其下的所有内容(如果存在);/.git/
不是典型的.gitignore
文件,因为 Git 会自动忽略它,因此通常被认为是“未被忽略”git check-ignore
.
git check-ignore
将打印出--non-matching
文件仅在--verbose
模式,因为它仅在该模式下打印出额外信息,告诉您文件是否被忽略。 (它总是打印被忽略的文件。)路径以以下格式每行显示一个
source:linenum:patternpath
以冒号分隔的字段是有关导致路径被忽略的原因的信息(例如路径中的一行).gitignore
文件),如果该文件不被忽略,则将为空。
The sed
然后命令过滤输出以仅显示被忽略文件的路径。这-n
选项告诉它默认不打印输入行。第一个替换模式替换<TAB>./
只用<TAB>
,删除领先的./
,纯粹出于审美原因。第二次替换完成了真正的工作,删除了任何::<TAB>
(表示没有“忽略”信息)开始一行,如果发生替换,则打印该行的剩余内容,这是一个不可忽略的路径。
您可以进一步过滤以进行额外的处理;我为一个脚本构建了这个脚本,该脚本可以按照以下方式进行降价检查:
markdownlint $(find_nonignored | grep '\.md$')
Notes
此代码在输出中包含未跟踪的文件(即从未添加到 Git 存储库或暂存),这通常是您想要的。 (例如,测试系统仍然应该检查新文件,甚至在它们之前git add
)请注意,其他解决方案涉及git ls-files
之类的人通常不会这样做。
上面的代码依赖于使用GNUsed
,这解释了\t
作为选项卡。如果您使用的是 BSDsed
(例如在 MacOS 上)您可能需要稍微调整一下。检查评论,看看是否有人有这方面的提示。
这里的所有代码都会在带有空格或其他“不寻常”字符的路径上中断;它需要在几个地方进行修改(例如使用-print0
with find
)来解决这个问题。为了使解释简单,我不会在这里解决此类问题。我还为其他人留下了该函数的泛化,以便在任意路径上工作,而不仅仅是当前工作目录。