=====
Paths
=====

This page describes files, sequences of files, and file filters. The
base type used is
`java.io.File <http://download.oracle.com/javase/6/docs/api/java/io/File.html>`_,
but several methods are augmented through implicits:

-  `RichFile <../../api/sbt/RichFile.html>`_
   adds methods to ``File``
-  `PathFinder <../../api/sbt/PathFinder.html>`_
   adds methods to ``File`` and ``Seq[File]``
-  `Path <../../api/sbt/Path$.html>`_ and
   `IO <../../api/sbt/IO$.html>`_ provide
   general methods related to files and I/O.

Constructing a File
-------------------

sbt 0.10+ uses
`java.io.File <http://download.oracle.com/javase/6/docs/api/java/io/File.html>`_
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:

::

    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:

::

    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.

::

    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:

::

    unmanagedBase := baseDirectory.value /"custom_lib"

Or, more concisely:

::

    unmanagedBase := baseDirectory.value /"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:

::

    historyPath := Some( (baseDirectory in ThisBuild).value / ".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.

::

    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:

::

    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 ``*``:

::

    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:

::

    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:

::

    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,

::

    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:

::

    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:

::

      // 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:

::

    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 :doc:`Mapping-Files` page.

File Filters
------------

The argument to ``*`` and ``**`` is of type
`java.io.FileFilter <http://download.oracle.com/javase/6/docs/api/java/io/FileFilter.html>`_.
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:

::

    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":

::

    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:

::

    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.
