如何使用Gradle从包含TGZ的TAR中提取文件?

问题描述

我有一个tar文件,其中包含多个tar.gz文件一个Docker映像),我想从中提取一个文件。在shell脚本中执行此操作很简单,但是使用Gradle时似乎有些棘手。

这是我到目前为止所拥有的:

task extractOuter(type: copy) {
    dependsOn jibBuildTar
    from tarTree(file("${buildDir}/jib-image.tar"))
    include "*.tar.gz"
    into "${buildDir}/tgz"
}

task extractInner(type: copy) {
    dependsOn extractOuter
    from (filetree(dir: "${buildDir}/tgz").collect { tarTree(it) }) {
        include "**/filename"
        includeEmptyDirs = false
    }
    into "${buildDir}/files"
}

起初似乎可以正常运行,但事实证明它偶尔会失败:extractInner任务找不到文件。也许我没有正确使用Gradle的惰性评估。

如何使其工作?还是有完全不同,更优雅的方式?

解决方法

在shell脚本中执行此操作很简单

您可以通过使用Exec任务类型来继续使用Shell脚本。

但是使用Gradle时似乎有些棘手。

到目前为止,您拥有的是如何使用Gradle进行操作。 Gradle的优点是它不会执行已经发生的工作。有关更多详细信息,请参见Build Cache

起初它似乎可以工作,但是事实证明它偶尔会失败:extractInner任务找不到该文件。也许我没有正确使用Gradle的惰性评估。

在上面的链接文档(重点是我的)中指出了这一点:

某些任务,例如Copy或Jar,通常使缓存变得没有意义,因为Gradle只是将文件从一个位置复制到另一个位置。使不产生输出或没有任务动作的任务可缓存也是没有意义的。

因此,您已经声明了任务,但尚未配置它们以产生可能会或可能不会导致问题的任何输出,因为您希望输出会出现在任务相关项中。

由于Copy扩展了DefaultTask,因此您可以使用outputs来设置任务输出。

task extractOuter(type: Copy) {
    dependsOn jibBuildTar
    outputs.dir(file("$buildDir/tgz")
    from tarTree(file("${buildDir}/jib-image.tar"))
    include "*.tar.gz"
    into "${buildDir}/tgz"
}

task extractInner(type: Copy) {
    dependsOn extractOuter
    outputs.dir(file("$buildDir/files")
    from (fileTree(dir: "${buildDir}/tgz").collect { tarTree(it) }) {
        include "**/filename"
        includeEmptyDirs = false
    }
    into "${buildDir}/files"
}