我可以在 sbt 中相对复制文件吗?

Can I relative-copy files in sbt?

我有这样的目录结构:

a
  /one
    hey.class
    hey.tasty
    you.class
    you.tasty
  /two
    foo.class
    foo.tasty
    /three
      bar.class
      bar.tasty

b 
  /one
  /two
    /three

我需要一种方法将所有 .tasty 文件从 /a 中各自的位置复制到 sbt 任务中 /b 中的相应位置。

您可以通过以下方式创建 sbt 任务并传递原始文件夹和目标文件夹:

val copyTasties = inputKey[Unit]("Copy .tasty files")

copyTasties := {
  val userInput = Def.spaceDelimited().parsed
  if (userInput.size != 2) {
    throw new IllegalArgumentException("Original and target directories should be define!")
  }
  val from = Paths.get(userInput.head)
  val to = Paths.get(userInput.last)

  Files
    .walk(from)
    .filter(Files.isRegularFile(_))
    .filter(path => path.toString.endsWith("tasty"))
    .forEach { original =>
      val relative = from.relativize(original)
      val destination = to.resolve(relative)
      IO.copyFile(original.toFile, destination.toFile)
    }
}

然后你可以这样调用它:

copyTasties C:\Dev\sandbox\a C:\Dev\sandbox\b

如果原始和目标稳定(例如它们是项目内的目录),您可以重写任务:

import java.nio.file.{Files, Paths}

import sbt._

val copyTastiesHardcoded = taskKey[Unit]("Copy .tasty files")

copyTastiesHardcoded := {
  val baseDir = baseDirectory.value.toPath

  val from = baseDir.resolve("a")
  val to = baseDir.resolve("b")

  Files
    .walk(from)
    .filter(Files.isRegularFile(_))
    .filter(path => path.toString.endsWith("tasty"))
    .forEach { original =>
      val relative = from.relativize(original)
      val destination = to.resolve(relative)
      IO.copyFile(original.toFile, destination.toFile)
    }
}

并在没有参数的情况下调用它

copyTastiesHardcoded

sbt 中有一些有用的实用方法可以帮助您查找文件并复制它们。不幸的是,它混合使用了传统的 java.io.File 和更现代的 java.nio.file.Path,因此您需要在它们之间进行转换:

val copyFiles = taskKey[Unit]("copy files")
copyFiles := {
  val inputDir = baseDirectory.value.toPath / "a"
  val files: Seq[(Path, FileAttributes)] =
    FileTreeView.default.list(inputDir.toGlob / RecursiveGlob / "*.tasty")
  val outputDir = baseDirectory.value.toPath / "b"
  IO.copy {
    files.map { case (p, _) =>
      p.toFile -> outputDir.resolve(inputDir.relativize(p)).toFile
    }
  }
}

请注意,我在这里使用 glob 来查找文件: https://www.scala-sbt.org/1.x/docs/Globs.html