# Chapter 14. Working With Files

This chapter is a work in progress.

Most builds work with files. Gradle adds some concepts and APIs to help you do this.

## 14.1. Locating files

You can locate a file relative to the project directory using the `Project.file()` method.

Example 14.1. Locating files

`build.gradle`

    // Using a relative path
    File configFile = file('src/config.xml')

    // Using an absolute path
    configFile = file(configFile.absolutePath)

    // Using a File object with a relative path
    configFile = file(new File('src/config.xml'))

You can pass any object to the `file()` method, though usually you would pass it a `String` or `File`. The supplied object's `toString()` value is treated as a file path. If this path is an absolute path, it is used to construct a `File` instance. Otherwise, a `File` instance is constructed by prepending the project directory path to the supplied path.

Using this method is a useful way to convert some user provided value into an absolute `File`. It is preferable to using `new File(somePath)`, as `file()` always evaluates the supplied path relative to the project directory, which is fixed, rather than the current working directory, which may not always be the same.

## 14.2. File collections

A file collection is simply a set of files. It is represented by the `FileCollection` interface. Many objects in Gradle implement this interface. For example, dependency configurations implement `FileCollection`.

One way to obtain a `FileCollection` instance is to use the `Project.files()` method. You can pass this method any number of objects, which are then converted into a set of `File` objects. The `files()` method accepts `File` and `String` arguments. These are evaluated relative to the project directory, as described in Section 14.1, “Locating files”. You can also pass collections, maps and arrays to the `files()` method. These are flattened and the contents converted to `File` instances.

Example 14.2. Creating a file collection

`build.gradle`

    FileCollection collection = files('src/file1.txt', file('src/file2.txt'), ['src/file3.txt', 'src/file4.txt'])

A file collection is iterable, and can be converted to a number of other types using the `as` operator. You can also add 2 file collections together using the `+` operator. Here are some examples.

Example 14.3. Using a file collection

`build.gradle`

    // Iterate over the files in the collection
    collection.each {File file ->
        file.name
    }

    // Convert the collection to various types
    Set set = collection.files
    Set set2 = collection as Set
    List list = collection as List
    String path = collection.asPath
    File file = collection.singleFile
    File file2 = collection as File

    // Add collections together
    def collection2 = collection + files('src/file3.txt')

You can also pass the `files()` method a closure or a `Callable` instance. This is called when the contents of the collection are queried, and its return value is converted to a set of `File` instances. The return value can be an object of any of the types supported by the `files()` method. This is a simple way to 'implement' the `FileCollection` interface.

Example 14.4. Implementing a file collection

`build.gradle`

    task list << {
        File srcDir

        // Create a file collection using a closure
        collection = files { srcDir.listFiles() }

        // Create a file collection using a Callable
        Callable callable = { srcDir.listFiles() } as Callable
        collection = files(callable)

        srcDir = file('src')
        println "Contents of $srcDir.name"
        collection.each { println relativePath(it) }

        srcDir = file('src2')
        println "Contents of $srcDir.name"
        collection.each { println relativePath(it) }
    }

Output of `gradle -q list`

    > gradle -q list
    Contents of src
    src/dir1
    src/file1.txt
    Contents of src2
    src2/dir1
    src2/dir2

The `files()` method also accepts `FileCollection` instances.

## 14.3. File trees

A file tree is a hierarchy of files, such as a directory tree. It is represented by the `FileTree` interface. The `FileTree` interface extends `FileCollection`, so you can treat a file tree exactly the same way as you would a file collection. Several objects in Gradle implement the `FileTree` interface, such as source sets.

One way to obtain a `FileTree` instance is to use the `Project.fileTree()` method. This creates a `FileTree` defined with a base directory, and optionally some Ant-style include and exclude patterns.

Example 14.5. Creating a file tree

`build.gradle`

    // Create a file tree with a base directory
    def tree = fileTree(dir: 'src/main')

    // Add include and exclude patterns to the tree
    tree.include '**/*.java'
    tree.exclude '**/Abstract*'

    // Create a tree using path
    tree = fileTree('src').include('**/*.java')

    // Create a tree using closure
    tree = fileTree {
        from 'src'
        include '**/*.java'
    }

    // Create a tree using a map
    tree = fileTree(dir: 'src', includes: ['**/*.java'])

You use a file tree in the same way you use a file collection. You can also visit the contents of the tree, and select a subtree using Ant-style patterns:

Example 14.6. Using a file tree

`build.gradle`

    // Iterate over the contents of a tree
    tree.each {File file ->
        println file
    }

    // Filter a tree
    def filtered = tree.matching {
        include 'org/gradle/api/**'
    }

    // Add trees together
    def sum = tree + fileTree(dir: 'src/test')

    // Visit the nodes of the tree
    tree.visit {node ->
        println "$node.relativePath => $node.file"
    }

## 14.4. Specifying a set of files

Many objects in Gradle have properties which accept a logical set of files. For example, the `Compile` task has a `source` property, which defines the source files to compile. You can set the value of this property using any of the types supported by the files() method, which we have seen above. This means you can set the property using, for example, a `File`, `String`, collection, `FileCollection` or even a closure. Here are some examples:

Example 14.7. Specifying a set of files

`build.gradle`

    compile {
        source = file('src/main/java')
    }

    compile {
        source = 'src/main/java'
    }

    compile {
        source = ['src/main/java', '../shared/java']
    }

    compile {
        source = fileTree(dir: 'src/main/java').matching { include 'org/gradle/api/**' }
    }

    compile {
        source = {
            fileTree(dir: 'src/main/java') + fileTree(dir: '../shared/java')
        }
    }

Usually, there is a method with the same name as the property, which appends to the set of files. Again, this method accepts any of the types supported by the files() method.

Example 14.8. Specifying a set of files

`build.gradle`

    compile {
        source 'src/main/java', 'src/main/groovy'
        source file('../shared/java')
        source { file('src/test/').listFiles() }
    }

## 14.5. Copying files

You can use the `Copy` task to copy files. The copy task allows you to filter the contents of the files as they are copied, and to map the files names.

Example 14.9. Copying files using the copy task

`build.gradle`

    task copyTask(type: Copy) {
        from 'src/main/webapp'
        into 'build/explodedWar'
        include '**/*.html'
        include '**/*.jsp'
        include 'assets/**'
    }

You can also use the `Project.copy()` method.

Example 14.10. Copying files using the copy() method

`build.gradle`

    task copyMethod << {
        copy {
            from 'src/main/webapp'
            into 'build/explodedWar'
            include '**/*.html'
            include '**/*.jsp'
            include 'assets/**'
        }
    }