mirror of https://github.com/sbt/sbt.git
197 lines
7.4 KiB
Markdown
197 lines
7.4 KiB
Markdown
[java.io.File]: http://download.oracle.com/javase/6/docs/api/java/io/File.html
|
|
[java.io.FileFilter]: http://download.oracle.com/javase/6/docs/api/java/io/FileFilter.html
|
|
[RichFile]: http://harrah.github.com/xsbt/latest/api/sbt/RichFile.html
|
|
[PathFinder]: http://harrah.github.com/xsbt/latest/api/sbt/PathFinder.html
|
|
[Path]: http://harrah.github.com/xsbt/latest/api/sbt/Path$.html
|
|
[IO]: http://harrah.github.com/xsbt/latest/api/sbt/IO$.html
|
|
|
|
# Paths
|
|
|
|
This page describes files, sequences of files, and file filters. The base type used is [java.io.File], but several methods are augmented through implicits:
|
|
|
|
* [RichFile] adds methods to `File`
|
|
* [PathFinder] adds methods to `File` and `Seq[File]`
|
|
* [Path] and [IO] provide general methods related to files and I/O.
|
|
|
|
## Constructing a File
|
|
|
|
sbt 0.10+ uses [java.io.File] to represent a file instead of the custom `sbt.Path` class that was in sbt 0.7 and earlier.
|
|
sbt defines the alias `File` for `java.io.File` so that an extra import is not necessary.
|
|
The `file` method is an alias for the single-argument `File` constructor to simplify constructing a new file from a String:
|
|
|
|
```scala
|
|
val source: File = file("/home/user/code/A.scala")
|
|
```
|
|
|
|
Additionally, sbt augments File with a `/` method, which is an alias for the two-argument `File` constructor for building up a path:
|
|
|
|
```scala
|
|
def readme(base: File): File = base / "README"
|
|
```
|
|
|
|
Relative files should only be used when defining the base directory of a `Project`, where they will be resolved properly.
|
|
|
|
```scala
|
|
val root = Project("root", file("."))
|
|
```
|
|
|
|
Elsewhere, files should be absolute or be built up from an absolute base `File`. The `baseDirectory` setting defines the base directory of the build or project depending on the scope.
|
|
|
|
For example, the following setting sets the unmanaged library directory to be the "custom_lib" directory in a project's base directory:
|
|
|
|
```scala
|
|
unmanagedBase <<= baseDirectory( (base: File) => base /"custom_lib" )
|
|
```
|
|
|
|
Or, more concisely:
|
|
|
|
```scala
|
|
unmanagedBase <<= baseDirectory( _ /"custom_lib" )
|
|
```
|
|
|
|
This setting sets the location of the shell history to be in the base directory of the build, irrespective of the project the setting is defined in:
|
|
|
|
```scala
|
|
historyPath <<= (baseDirectory in ThisBuild)(t => Some(t / ".history")),
|
|
```
|
|
|
|
## Path Finders
|
|
|
|
A `PathFinder` computes a `Seq[File]` on demand. It is a way to build a sequence of files. There are several methods that augment `File` and `Seq[File]` to construct a `PathFinder`. Ultimately, call `get` on the resulting `PathFinder` to evaluate it and get back a `Seq[File]`.
|
|
|
|
### Selecting descendants
|
|
|
|
The `**` method accepts a `java.io.FileFilter` and selects all files matching that filter.
|
|
|
|
```scala
|
|
def scalaSources(base: File): PathFinder = (base / "src") ** "*.scala"
|
|
```
|
|
|
|
### get
|
|
|
|
This selects all files that end in `.scala` that are in `src` or a descendent directory. The list of files is not actually evaluated until `get` is called:
|
|
|
|
```scala
|
|
def scalaSources(base: File): Seq[File] = {
|
|
val finder: PathFinder = (base / "src") ** "*.scala"
|
|
finder.get
|
|
}
|
|
```
|
|
|
|
If the filesystem changes, a second call to `get` on the same `PathFinder` object will reflect the changes. That is, the `get` method reconstructs the list of files each time. Also, `get` only returns `File`s that existed at the time it was called.
|
|
|
|
### Selecting children
|
|
|
|
Selecting files that are immediate children of a subdirectory is done with a single `*`:
|
|
|
|
```scala
|
|
def scalaSources(base: File): PathFinder = (base / "src") * "*.scala"
|
|
```
|
|
|
|
This selects all files that end in `.scala` that are in the `src` directory.
|
|
|
|
### Existing files only
|
|
|
|
If a selector, such as `/`, `**`, or `*, is used on a path that does not represent a directory, the path list will be empty:
|
|
|
|
```scala
|
|
def emptyFinder(base: File) = (base / "lib" / "ivy.jar") * "not_possible"
|
|
```
|
|
|
|
### Name Filter
|
|
|
|
The argument to the child and descendent selectors `*` and `**` is actually a `NameFilter`. An implicit is used to convert a `String` to a `NameFilter` that interprets `*` to represent zero or more characters of any value. See the Name Filters section below for more information.
|
|
|
|
### Combining PathFinders
|
|
|
|
Another operation is concatenation of `PathFinder`s:
|
|
|
|
```scala
|
|
def multiPath(base: File): PathFinder =
|
|
(base / "src" / "main") +++
|
|
(base / "lib") +++
|
|
(base / "target" / "classes")
|
|
```
|
|
|
|
When evaluated using `get`, this will return `src/main/`, `lib/`, and `target/classes/`. The concatenated finder supports all standard methods. For example,
|
|
|
|
```scala
|
|
def jars(base: File): PathFinder =
|
|
(base / "lib" +++ base / "target") * "*.jar"
|
|
```
|
|
|
|
selects all jars directly in the "lib" and "target" directories.
|
|
|
|
A common problem is excluding version control directories. This can be accomplished as follows:
|
|
|
|
```scala
|
|
def sources(base: File) =
|
|
( (base / "src") ** "*.scala") --- ( (base / "src") ** ".svn" ** "*.scala")
|
|
```
|
|
|
|
The first selector selects all Scala sources and the second selects all sources that are a descendent of a `.svn` directory. The `---` method removes all files returned by the second selector from the sequence of files returned by the first selector.
|
|
|
|
### Filtering
|
|
|
|
There is a `filter` method that accepts a predicate of type `File => Boolean` and is non-strict:
|
|
|
|
```scala
|
|
// 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
|
|
```
|
|
|
|
### Empty PathFinder
|
|
|
|
`PathFinder.empty` is a `PathFinder` that returns the empty sequence when `get` is called:
|
|
|
|
```scala
|
|
assert( PathFinder.empty.get == Seq[File]() )
|
|
```
|
|
|
|
### PathFinder to String conversions
|
|
|
|
Convert a `PathFinder` to a String using one of the following methods:
|
|
|
|
* `toString` is for debugging. It puts the absolute path of each component on its own line.
|
|
* `absString` gets the absolute paths of each component and separates them by the platform's path separator.
|
|
* `getPaths` produces a `Seq[String]` containing the absolute paths of each component
|
|
|
|
### Mappings
|
|
|
|
The packaging and file copying methods in sbt expect values of type `Seq[(File,String)]` and `Seq[(File,File)]`, respectively.
|
|
These are mappings from the input file to its (String) path in the jar or its (File) destination.
|
|
This approach replaces the relative path approach (using the `##` method) from earlier versions of sbt.
|
|
|
|
Mappings are discussed in detail on the [[Mapping Files]] page.
|
|
|
|
## File Filters
|
|
|
|
The argument to `*` and `**` is of type [java.io.FileFilter].
|
|
sbt provides combinators for constructing `FileFilter`s.
|
|
|
|
First, a String may be implicitly converted to a `FileFilter`.
|
|
The resulting filter selects files with a name matching the string, with a `*` in the string interpreted as a wildcard.
|
|
For example, the following selects all Scala sources with the word "Test" in them:
|
|
|
|
```scala
|
|
def testSrcs(base: File): PathFinder = (base / "src") * "*Test*.scala"
|
|
```
|
|
|
|
There are some useful combinators added to `FileFilter`. The `||` method declares alternative `FileFilter`s. The following example selects all Java or Scala source files under "src":
|
|
|
|
```scala
|
|
def sources(base: File): PathFinder = (base / "src") ** ("*.scala" || "*.java")
|
|
```
|
|
|
|
The `--`method excludes a files matching a second filter from the files matched by the first:
|
|
|
|
```scala
|
|
def imageResources(base: File): PathFinder =
|
|
(base/"src"/"main"/"resources") * ("*.png" -- "logo.png")
|
|
```
|
|
|
|
This will get `right.png` and `left.png`, but not `logo.png`, for example.
|