获取包含字符串或模式的文件列表

Get list of files containing string(s) or pattern(s)

是否有 Gradle 模式用于检索一个文件夹或一组文件夹中包含给定字符串、字符串集或模式的文件列表?

我的项目生成 RPM 并使用 Nebula RPM 类型(很棒的包!)。有几组不同类型的文件需要 post 处理。我正在尝试生成包含字符串的文件列表,这些字符串是 post 处理的指标。例如,包含“@doc”的文件需要由文档生成器脚本处理。包含“@HOSTNAME@”和“@HOSTFQDN@”的文件需要经过sed处理,将字符串替换为实际的主机名或主机fqdn。

包中的搜索根将为 src\main\resources。结果,构建脚本设置了 post-install 脚本命令——类似于:

postInstall('/opt/product/bin/postprocess.sh ' + join(filesContainingDocs, " "))
postInstall('/bin/sed -i -e "s/@HOSTNAME@/$(hostname -s)/" -e s/@HOSTFQDN@/$(hostname)/" ' + join(filesContainingHostname, " ")

我可以弄清楚 post 安装语法。我很难找到任何对文件内容而不是文件名进行操作的常规 Gradle 'things'(即 FileTree)的过滤器。我将如何填充 filesContainingDocs 和 filesContainingHostname - 类似于:

filesContainingDocs = FileTree('src/main/resources', { contents.matches('@doc') }
filesContainingHostname = FileTree('src/main/resources', { contents.matches('@(HOSTNAME|HOSTFQDN)@') }

虽然 post-process 脚本可以简单地执行 grep,但我们产品中的几个 RPM 相互重叠并且每个 RPM 应该只 post-process 它提供的文件,所以一般对最终安装的文件夹进行 grep 是行不通的 - 它会捕获其他 RPM 提供的文件。在我看来,我应该能够在构建时从包含给定 RPM 项目的更大的源文件集中生成正确的静态文件列表。

它不一定是 FileTree - 运行 像 findstr /s /m /c:"@doc" src\main\resources\*.conf 这样的命令(唉,构建平台是 Windows)在标准输出中产生答案,但我不是确定如何将该结果放入对象 Gradle 可用于扩展结果。 (我还怀疑有一个 'more Gradle way' 可以做到这一点。)

文件集以及这些文件的内容通常很小。

I'm having difficulty finding the filter for any of the regular Gradle 'things' (i.e., FileTree) that operate on contents of files rather than names of files.

您可以在 Gradle 文件树上应用您能想到的任何过滤器,最终它只是 JVM 中的 Groovy(或 Kotlin)代码 运行。每个 Gradle FileTree is nothing more than a (lazily evaluated) collection of Java File objects. To filter those File objects, you can read their content, e.g. in the same way you would read them in Java. Groovy even provides a JDK enhancement for the Java class File 包含用于此目的的简单方法 getText()。现在您可以轻松过滤包含特定字符串的文件:

filesContainingDocs = fileTree('src/main/resources').filter { file ->
    file.text.contains('@doc')
}

使用 Groovy,您可以像访问字段一样调用 .getText() 等 getter(在本例中为 .text)。

如果简单的 contains 检查还不够,Groovy JDK 增强功能甚至在 CharSequence/[=22= 上提供了方法 matches(Pattern pattern) ] 实例以执行常规扩展检查:

filesContainingDocs = fileTree('src/main/resources').filter { file ->
    file.text.replace('\r\n','\n').matches('.*some regex.*') }
}