Reputation: 1677
I am trying to copy one file to multiple destinations through a Gradle task. I found the following in other websites but I get an ERROR while running this task.
def filesToCopy = copySpec{
from 'somefile.jar'
rename {String fileName -> 'anotherfile.jar'}
}
task copyFile(type:Copy) {
with filesToCopy {
into 'dest1/'
}
with filesToCopy {
into 'dest2/'
}
}
ERROR
No signature of method: org.gradle.api.internal.file.copy.CopySpecImpl.call() is applicable for argument types
Is there a way to copy to multiple destinations in one Gradle task?
Upvotes: 62
Views: 48364
Reputation: 21
For seekers. You can use it. Example:
fun getModulesUsingSubmodule(submoduleName: String): List<String> {
val result = mutableListOf<String>()
rootProject.allprojects.forEach { project ->
project.configurations.forEach { configuration ->
if (configuration.dependencies.any { dependency -> dependency.name == submoduleName }) {
result.add(project.name)
}
}
}
return result
}
tasks.register("copyLiquibaseResourcesToModule") {
dependsOn(tasks.processResources)
val buildSrcDir = layout.buildDirectory.dir("resources/main/liquibase")
val srcAbsolutePath = buildSrcDir.get().asFile.absolutePath
val rootProjectName = rootProject.name
val resourcesPath = "/resources/main/db"
doFirst {
val modulesUsingDatabase = getModulesUsingSubmodule(project.name)
println("Copy resources from '$srcAbsolutePath'")
modulesUsingDatabase.forEach { moduleName ->
val targetAbsolutePath: String = if (rootProjectName == moduleName) {
"${rootProject.buildDir}${resourcesPath}"
} else {
"${rootProject.project(":$moduleName").buildDir}${resourcesPath}"
}
println("To module '$moduleName' catalog: $targetAbsolutePath")
copy {
from(srcAbsolutePath)
into(targetAbsolutePath)
}
}
}
doLast {
println("Clean resources: '$srcAbsolutePath'!")
delete(buildSrcDir)
}
}
Upvotes: 0
Reputation: 1574
I needed to do this in a particular order to rewrite a particular string on a set of files.
task copyAtoB(dependsOn: [existingTask]) {
doLast {
copy {
from("folder/a") {
include "*.java"
}
// Have to use a new path for modified files
into("folder/b")
filter {
String line ->
line.replaceAll("changeme", "to this")
}
}
}
}
task overwriteFilesInAfromB(dependsOn: [copyAtoB]) {
doLast {
copy {
from("folder/b") {
include "*.java"
}
into("folder/a")
}
}
}
// Finally, delete the files in folder B
task deleteB(type: Delete, dependsOn: overwriteFilesInAfromB) {
delete("folder/b")
}
nextTask.dependsOn(deleteB)
Upvotes: 0
Reputation: 28663
no there isn't a way to do that atm. I would create seperate gradle tasks for each target directory
def filesToCopy = copySpec{
from 'somefile.jar'
rename {String fileName -> 'anotherfile.jar'}
}
task copyFileDest1(type:Copy) {
with filesToCopy
into 'dest1/'
}
task filesToCopyDest2(type:Copy) {
with filesToCopy
into 'dest2/'
}
Upvotes: 14
Reputation: 886
Here is a general snippet without copySpec for Gradle 4.1. As pointed out the trick is to use a base into and use relative into inside the closures (e.g. from closure).
task multiIntoCopy(type: Copy){
into(projectDir) // copy into relative to this
from("foo"){
into("copied/foo") // will be projectDir/copied/foo
// just standard copy stuff
rename("a.txt", "x.txt")
}
from("bar"){
into("copied/aswell/bar") // projectDir/copied/copied/aswell/bar
}
from("baz") // baz folder content will get copied into projectDir
//from("/bar"){ // this will mess things up, be very careful with the paths
// into("copied/aswell/bar")
//}
}
Upvotes: 26
Reputation: 16408
If your destination paths share a common path prefix (dest_base
), then you can use something like this:
def filesToCopy = copySpec {
from 'somefile.jar'
rename { String fileName -> 'anotherfile.jar' }
}
task copyFile(type: Copy) {
into 'dest_base'
into('dest1') {
with filesToCopy
}
into('dest2') {
with filesToCopy
}
}
Compared to other answers which use the copy
method, this approach also retains Gradle’s UP-TO-DATE checks.
The above snippet would result in output like this:
dest_base/
├── dest1
│ └── anotherfile.jar
└── dest2
└── anotherfile.jar
Upvotes: 24
Reputation: 3495
an alternative way
task myCustomTask << {
copy {
from 'sourcePath/folderA'
into 'targetPath/folderA'
}
copy {
from 'sourcePath/folderB'
into 'targetPath/folderB'
}
copy {
from 'sourcePath/fileA.java','sourcePath/fileB.java'
into 'targetPath/folderC'
}
}
Upvotes: 47
Reputation: 2585
If you really want them in one task, you do something like this:
def filesToCopy = copySpec {
from 'someFile.jar'
rename { 'anotherfile.jar' }
}
task copyFiles << {
['dest1', 'dest2'].each { dest ->
copy {
with filesToCopy
into dest
}
}
}
Upvotes: 46