1. 路径

路径 

本页描述文件、文件序列和文件过滤器。使用的基本类型是 java.io.File,但一些方法通过隐式函数进行了扩展

  • RichFile 为 File 添加了方法
  • PathFinder 为 File 和 Seq[File] 添加了方法
  • PathIO 提供了与文件和 I/O 相关的通用方法。

构造 File 

sbt 使用 java.io.File 来表示文件,并定义了类型别名 File 用于 java.io.File,因此不需要额外的导入。file 方法是单参数 File 构造函数的别名,用于简化从字符串构造新文件的操作

val source: File = file("/home/user/code/A.scala")

此外,sbt 为 File 扩展了 / 方法,它是用于构建路径的双参数 File 构造函数的别名

def readme(base: File): File = base / "README"

相对文件仅应在定义 Project 的基目录时使用,在那里它们将被正确解析。

val root = Project("root", file("."))

在其他地方,文件应为绝对路径,或从绝对基目录 File 构建。baseDirectory 设置定义了构建或项目的基目录,具体取决于范围。

例如,以下设置将非管理库目录设置为项目基目录中的“custom_lib”目录

unmanagedBase := baseDirectory.value /"custom_lib"

或者,更简洁地说

unmanagedBase := baseDirectory.value /"custom_lib"

此设置将 shell 历史记录的位置设置为构建的基目录,与定义该设置的项目无关

historyPath := Some( (ThisBuild / baseDirectory).value / ".history"),

路径查找器 

PathFinder 在需要时计算 Seq[File]。它是一种构建文件序列的方式。有一些方法会扩展 FileSeq[File] 来构造 PathFinder。最终,在结果 PathFinder 上调用 get 来评估它并获取 Seq[File]

选择子孙 

** 方法接受 java.io.FileFilter 并选择与该过滤器匹配的所有文件。

def scalaSources(base: File): PathFinder = (base / "src") ** "*.scala"

get 

这将选择所有在 src 或子目录中以 .scala 结尾的文件。文件列表实际上直到调用 get 才会被评估

def scalaSources(base: File): Seq[File] = {
  val finder: PathFinder = (base / "src") ** "*.scala" 
  finder.get
}

如果文件系统发生变化,对同一 PathFinder 对象的第二次 get 调用将反映这些变化。也就是说,get 方法每次都会重建文件列表。此外,get 仅返回在调用时存在的 File

选择子节点 

选择作为子目录的直接子节点的文件可以使用单个 * 完成

def scalaSources(base: File): PathFinder = (base / "src") * "*.scala"

这将选择所有在 src 目录中以 .scala 结尾的文件。

仅现有文件 

如果对不表示目录的路径使用选择器,例如 /***,路径列表将为空

def emptyFinder(base: File) = (base / "lib" / "ivy.jar") * "not_possible"

名称过滤器 

子节点和子孙选择器 *** 的参数实际上是 NameFilter。隐式函数用于将 String 转换为 NameFilter,该过滤器将 * 解释为零个或多个任意值的字符。有关详细信息,请参阅下面的名称过滤器部分。

组合 PathFinder 

另一个操作是 PathFinder 的连接

def multiPath(base: File): PathFinder =
   (base / "src" / "main") +++
   (base / "lib") +++
   (base / "target" / "classes")

使用 get 评估时,这将返回 src/main/lib/target/classes/。连接的查找器支持所有标准方法。例如,

def jars(base: File): PathFinder =
   (base / "lib" +++ base / "target") * "*.jar"

选择“lib”和“target”目录中的所有 jar 文件。

一个常见的问题是排除版本控制目录。这可以通过以下方法实现

def sources(base: File) =
   ( (base / "src") ** "*.scala") --- ( (base / "src") ** ".svn" ** "*.scala")

第一个选择器选择所有 Scala 源代码,第二个选择器选择所有作为 .svn 目录子孙的源代码。--- 方法从第一个选择器返回的文件序列中删除第二个选择器返回的所有文件。

过滤 

有一个 filter 方法接受类型为 File => Boolean 的谓词,并且是非严格的

// selects all directories under "src"
def srcDirs(base: File) = ( (base / "src") ** "*") filter { _.isDirectory }

// selects archives (.zip or .jar) that are selected by 'somePathFinder'
def archivesOnly(base: PathFinder) = base filter ClasspathUtilities.isArchive

空 PathFinder 

PathFinder.empty 是一个 PathFinder,在调用 get 时返回空序列

assert( PathFinder.empty.get == Seq[File]() )

PathFinder 到 String 的转换 

使用以下方法之一将 PathFinder 转换为 String

  • toString 用于调试。它将每个组件的绝对路径放在单独的行上。
  • absString 获取每个组件的绝对路径,并用平台的路径分隔符分隔它们。
  • getPaths 生成包含每个组件的绝对路径的 Seq[String]

映射 

sbt 中的打包和文件复制方法分别期望类型为 Seq[(File,String)]Seq[(File,File)] 的值。这些是输入文件与其在 jar 文件中的(String)路径或其(File)目标的映射。这种方法替换了早期 sbt 版本中使用的相对路径方法(使用 ## 方法)。

映射在 Mapping-Files 页面上有详细的讨论。

文件过滤器 

*** 的参数的类型是 java.io.FileFilter。sbt 提供了用于构造 FileFilter 的组合器。

首先,String 可以隐式转换为 FileFilter。结果过滤器选择名称与字符串匹配的文件,字符串中的 * 解释为通配符。例如,以下代码选择所有包含单词“Test”的 Scala 源代码

def testSrcs(base: File): PathFinder =  (base / "src") * "*Test*.scala"

FileFilter 中添加了一些有用的组合器。|| 方法声明了备选 FileFilter。以下示例选择“src”下的所有 Java 或 Scala 源代码文件

def sources(base: File): PathFinder  =  (base / "src") ** ("*.scala" || "*.java")

-- 方法从第一个过滤器匹配的文件中排除与第二个过滤器匹配的文件

def imageResources(base: File): PathFinder =
   (base/"src"/"main"/"resources") * ("*.png" -- "logo.png")

例如,这将获取 right.pngleft.png,但不会获取 logo.png