Могу ли я относительное копирование файлов в sbt?

#scala #sbt

#scala #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 в соответствующие места в /b в задаче sbt.

Ответ №1:

Вы можете создать задачу 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
  

Ответ №2:

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

Обратите внимание, что я использую глобус здесь, чтобы найти файлы:
https://www.scala-sbt.org/1.x/docs/Globs.html