Gradle:如何将绝对路径列表复制到单个目录中

Gradle:如何将绝对路径列表复制到单个目录中,gradle,groovy,Gradle,Groovy,在Gradle中,我试图将绝对路径列表复制到单个目录中,但我希望将绝对路径的最后一个组件保留为目标目录的子文件夹 目前我有: def copyTask = tasks.create(name: "copyFolders", type: Copy, overwrite: true) { from ["/sources/a-1/first", "/sources/a-3/b-1/c-1/second"] into "/destination" } 但这会导致/sources/foo

在Gradle中,我试图将绝对路径列表复制到单个目录中,但我希望将绝对路径的最后一个组件保留为目标目录的子文件夹

目前我有:

def copyTask = tasks.create(name: "copyFolders", type: Copy, overwrite: true) {
    from ["/sources/a-1/first", "/sources/a-3/b-1/c-1/second"]
    into "/destination"
}
但这会导致
/sources/foo/bar
/sources/one/two/three/path
中包含的文件被复制到
/destination
中。相反,我希望
/destination
同时包含
bar
path
文件夹(其内容在其中)


它应该能够正确处理这种情况:

sources
├── a-1
│   └── fist
│       └── lorem.txt
|       └── subfolder
│           └── lorem2.txt
├── a-2
│   └── fist-b
│       └── lorem.txt
|       └── subfolder
│           └── lorem2.txt
└── a-3
    └── b-1
        └── c-1
            └── second
                └── ipsum.log
->


根据@szymon的回答,我得到:

def copyTask = tasks.create(name: "copyToDestDir", type: Copy, overwrite: true) {
    includeEmptyDirs = false
    def fromDir = "/sources"
    def sourcePaths = ["/sources/a-1/first", "/sources/a-3/b-1/c-1/second"]
    from fileTree(fromDir).dir.listFiles()
    eachFile { copySpec ->
        def shouldBeCopied = false
        sourcePaths.find {
            if (copySpec.getFile().getCanonicalPath().startsWith(it)) {
                shouldBeCopied = true
                return true // break iteration
            }
        }
        if (shouldBeCopied) {
            String[] parts = file.path.split('/')
            copySpec.path = parts.size() > 1 ? "${parts[parts.size() - 2]}/${parts[parts.size() - 1]}" : parts[0]
        } else {
            copySpec.exclude()
        }
    }
    into destDir
}
但这错误地导致:

destination
├── first
│   └── lorem.txt
└── subfolder
│    └── lorem2.txt
└── path
    └── ipsum.log


如何实现这一点?

尝试以下梯度任务:

task copyFiles(type: Copy, overwrite: true) {
    includeEmptyDirs = false
    from fileTree("sources").dir.listFiles()
    eachFile { file ->
        String[] parts = file.path.split('/')
        file.path = parts.size() > 1 ? "${parts[parts.size() - 2]}/${parts[parts.size() - 1]}" : parts[0]
    }
    into "destDir"
}
整个部分发生在
eachFile{}
闭包中,我们在闭包中指定了一个目标
文件.path
——我使用了这个命令式方法,但它可以替换为奇特的正则表达式,保留最后一个文件夹和文件名,并用空字符串替换所有其他部分(我尝试使用这样的正则表达式,但失败了)

工作原理 我的输入目录如下所示:

sources
├── foo
│   └── bar
│       └── lorem.txt
└── one
    └── two
        └── three
            └── path
                └── ipsum.log
destDir
├── bar
│   └── lorem.txt
└── path
    └── ipsum.log
我运行一个任务:

#: ./gradlew copyFiles                                                  
:copyFiles UP-TO-DATE

BUILD SUCCESSFUL
destDir
如下所示:

sources
├── foo
│   └── bar
│       └── lorem.txt
└── one
    └── two
        └── three
            └── path
                └── ipsum.log
destDir
├── bar
│   └── lorem.txt
└── path
    └── ipsum.log

通过Gradle
2.14.1
3.5-rc-2
4.2.1
测试,我终于解决了这个问题。请注意,需要顶级
into
指令,否则它将不起作用,而嵌套的
into
指令是相对于顶级指令的

def copyTask = tasks.create(name: "copyToDestDir", type: Copy, overwrite: true) {
    includeEmptyDirs = false
    def fromDir = "/sources"
    def sourcePaths = ["/sources/a-1/first", "/sources/a-3/b-1/c-1/second"]
    def destDir = "/destination"
    sourcePaths.each { sourcePath ->
        from(sourcePath) {
            into sourcePath.substring(sourcePath.lastIndexOf('/') + 1)
        }
    }
    into destDir
    dependsOn cleanUpDestDir
}

感谢@SzymonStepniak的启发。

感谢您的回答!这看起来很有希望。如果
bar
path
,以及他们的父母有我不感兴趣的兄弟目录,该怎么办?我解决了我在评论中提到的问题,但这个解决方案不起作用,因为
bar
path
的任何子文件夹都会被移动到根目录,而不是留在里面。