1. 路徑

路徑 

此頁面描述檔案、檔案序列和檔案篩選器。使用的基本類型是 java.io.File,但透過隱式擴充了幾個方法

  • RichFile 將方法新增至 File
  • PathFinder 將方法新增至 File 和 Seq[File]
  • PathIO 提供與檔案和 I/O 相關的一般方法。

建構 File 

sbt 使用 java.io.File 來表示檔案,並為 java.io.File 定義類型別名 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,這會將 * 解譯為代表零個或多個任何值字元。如需詳細資訊,請參閱下方的名稱篩選器章節。

合併 PathFinders 

另一個作業是 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 到字串的轉換 

使用下列其中一個方法將 PathFinder 轉換為字串

  • toString 用於偵錯。它會將每個元件的絕對路徑放在自己的行上。
  • absString 會取得每個元件的絕對路徑,並以平台的路徑分隔符號分隔它們。
  • getPaths 會產生一個 Seq[String],其中包含每個元件的絕對路徑

對應 

sbt 中的封裝和檔案複製方法會分別預期 Seq[(File,String)]Seq[(File,File)] 類型的值。這些是從輸入檔案到其在 jar 中的 (字串) 路徑或其 (檔案) 目標的對應。此方法會取代 sbt 先前版本中 (使用 ## 方法) 的相對路徑方法。

對應會在 Mapping-Files 頁面詳細討論。

檔案篩選器 

*** 的引數類型為 java.io.FileFilter。sbt 提供組合器來建構 FileFilter

首先,字串可能會隱式轉換為 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