Task with one or more output files

I have a task that takes an input source file and has one or more output files. The very first time the task is executed, everything is fine. But if I do a clean, gradle doesn’t see that the output files are gone and the task needs to be rerun. The confusion is understandable since I’m using a wildcard to specify the output files and beyond that I don’t know the output file names in advance.

Here is a minimal example (in Kotlin):

task(“clean”) {
delete(project.buildDir)
}

task(“one2many”) {
val source = “one.txt”
val manyFiles = “${project.buildDir}/many/*.txt”

inputs.file(source)
outputs.file(manyFiles)

commandLine("touch",
    "build/many/one-1.txt",
    "build/many/one-2.txt",
    "build/many/one-3.txt")

}

If I execute the clean command after one2many and then run one2many again, gradle says the task is up-to-date.

Is there a way to make this task run if there are no files that match “${project.buildDir}/many/*.txt”?

Thanks!

Try using outputs.dir(project.buildDir.resolve("many")) to specify that your output is every file in that directory. Not sure if this helps, but it may be a step in the right direction.

Thanks, Róbert! That does work. Although I don’t understand what role resolve is playing. I’m going to tinker with this some more.

It would also be nice to be able to specify a pattern for specific files in the directory and not just all files in the directory. But that’s a nice-to-have, not a requirement.

Note: I"m just a user like you.

File.resolve("foo") extension function in Kotlin is a nicer way of doing "${file}/foo", more typed and safe. For example if file is null resolve will throw NPE, but interpolation will give you null/foo and probably create a folder named null later on instead of failing. buildDir is non-null in this particular case, but in general it’s a better pattern I found.

You could do

outputs.files fileTree("${project.buildDir}/many").matching {
   include '*.txt'
}