【问题标题】:How to copy to multiple destinations with Gradle copy task?如何使用 Gradle 复制任务复制到多个目的地?
【发布时间】:2012-11-20 06:10:33
【问题描述】:

我正在尝试通过 Gradle 任务将一个文件复制到多个目标。我在其他网站上找到了以下内容,但在运行此任务时出现错误。

def filesToCopy = copySpec{
    from 'somefile.jar'
    rename {String fileName -> 'anotherfile.jar'}
}

task copyFile(type:Copy) {
    with filesToCopy  {
      into 'dest1/'
    }
    with filesToCopy  {
      into 'dest2/'
    }
}

错误

没有方法签名:org.gradle.api.internal.file.copy.CopySpecImpl.call() 适用于参数类型

有没有办法在一个 Gradle 任务中复制到多个目标?

【问题讨论】:

    标签: gradle


    【解决方案1】:

    如果您真的希望他们完成一项任务,请执行以下操作:

    def filesToCopy = copySpec {
      from 'someFile.jar'
      rename { 'anotherfile.jar' }
    }
    
    task copyFiles << {
      ['dest1', 'dest2'].each { dest ->
        copy {
          with filesToCopy
          into dest
        }
      }
    }
    

    【讨论】:

    • 这是一个非常方便的方法。但一个缺点是,当我为列表添加一个扩展变量时:ext.dispersalList = [ 'dest1', 'dest2', ... ];任务使用定义时间值(空)而不是“构建时间”值。这意味着我必须在子项目build.gradle 文件中重复定义相同的任务。有没有办法对任务进行参数化,以便构建更加DRY
    【解决方案2】:

    另一种方法

    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'
        }
    }
    

    【讨论】:

    • &lt;&lt; 在 Gradle 4.x 中被弃用,并在 Gradle 5.0 中被移除。请改用doLast {}
    【解决方案3】:

    具有共同的目标基本路径

    如果您的目标路径共享一个公共路径前缀 (dest_base),那么您可以使用如下内容:

    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
        }
    }
    

    与使用 copy 方法的其他答案相比,这种方法还保留了 Gradle 的 UP-TO-DATE 检查。

    上面的 sn-p 会产生如下输出:

    dest_base/
    ├── dest1
    │   └── anotherfile.jar
    └── dest2
        └── anotherfile.jar
    

    【讨论】:

    • 哇,我不知道具有各种CopySpecs 的多个目的地是可能的。我不知道这是否是 Gradle 的一些新功能,但它实际上是最好的解决方案,因为它提供了 UP-TO-DATE 检查 并且 不会创建多个任务(这可能很烦人对于大量的子目录)。
    • 这是一个合适的 Gradle 解决方案(也是最好的一个),因为正如作者所说,它将正确使用 Gradle 的增量构建缓存,并且仅构建(复制)输入源文件,如果它们与输出目标文件不同。
    【解决方案4】:

    这是 Gradle 4.1 的不带 copySpec 的一般 sn-p。正如所指出的那样,诀窍是在闭包内使用基础进入并使用相对进入(例如来自闭包)。

    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")
        //}
    }
    

    【讨论】:

    • 这不回答所提出的问题。目标是复制到多个目的地而不是从多个目的地
    • 这个应该是最佳答案。它唯一的缺陷是它要求目标路径具有相同的根,这在大多数情况下应该不是问题。
    • 这很好用,它能够将多个文件复制到多个目的地。要只复制一个文件,请在所有from()中使用相同的文件路径
    【解决方案5】:

    不,没有办法做到这一点。我会为每个目标目录创建单独的 gradle 任务

    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/'
    }
    

    【讨论】:

    • +1 这样您就可以保留 UP-TO-DATE 检查的好处(按照其他答案的建议直接调用 copy() 方法会丢失)
    • @dnault 我没有提到这一点,但绝对是一个好点。
    • 这是gradle方式+1,应该是公认的答案
    • filesToCopyDest2在哪里使用?
    • filesToCopyDest2 是一个任务
    【解决方案6】:

    我需要按特定顺序执行此操作,以便在一组文件上重写特定字符串。

    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)
    
    

    【讨论】:

      猜你喜欢
      • 2016-03-20
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 2020-10-06
      • 2012-10-22
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      相关资源
      最近更新 更多