// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[working_with_files]]
= Working With Files

Almost every Gradle build interacts with files in some way: think source files, file dependencies, reports and so on. That's why Gradle comes with a comprehensive API that makes it simple to perform the file operations you need.

The API has two parts to it:

 * Specifying which files and directories to process
 * Specifying what to do with them

The <<#sec:locating_files,File paths in depth>> section covers the first of these in detail, while subsequent sections, like <<#sec:copying_files,File copying in depth>>, cover the second. To begin with, we'll show you examples of the most common scenarios that users encounter.

[[sec:copying_single_file_example]]
== Copying a single file

You copy a file by creating an instance of Gradle's builtin link:{groovyDslPath}/org.gradle.api.tasks.Copy.html[Copy] task and configuring it with the location of the file and where you want to put it. This example mimics copying a generated report into a directory that will be packed into an archive, such as a ZIP or TAR:

.How to copy a single file
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-single-file-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-single-file-example]"]
====

The link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:file(java.lang.Object)[Project.file(java.lang.Object)] method is used to create a file or directory path relative to the current project and is a common way to make build scripts work regardless of the project path. The file and directory paths are then used to specify what file to copy using link:{groovyDslPath}/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:from(java.lang.Object++[]++)[Copy.from(java.lang.Object...)] and which directory to copy it to using link:{groovyDslPath}/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:into(java.lang.Object)[Copy.into(java.lang.Object)].

You can even use the path directly without the `file()` method, as explained early in the section <<#sec:copying_files,File copying in depth>>:

.Using implicit string paths
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-single-file-example-without-file-method]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-single-file-example-without-file-method]"]
====

Although hard-coded paths make for simple examples, they also make the build brittle. It's better to use a reliable, single source of truth, such as a task or shared project property. In the following modified example, we use a report task defined elsewhere that has the report's location stored in its `outputFile` property:

.Prefer task/project properties over hard-coded paths
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-single-file-example-with-task-properties]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-single-file-example-with-task-properties]"]
====

We have also assumed that the reports will be archived by `archiveReportsTask`, which provides us with the directory that will be archived and hence where we want to put the copies of the reports.

[[sec:copying_multiple_files_example]]
== Copying multiple files

You can extend the previous examples to multiple files very easily by providing multiple arguments to `from()`:

.Using multiple arguments with from()
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-multiple-files-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-multiple-files-example]"]
====

Two files are now copied into the archive directory. You can also use multiple `from()` statements to do the same thing, as shown in the first example of the section <<#sec:copying_files, File copying in depth>>.

Now consider another example: what if you want to copy all the PDFs in a directory without having to specify each one? To do this, attach inclusion and/or exclusion patterns to the copy specification. Here we use a string pattern to include PDFs only:

.Using a flat filter
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-multiple-files-with-flat-filter-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-multiple-files-with-flat-filter-example]"]
====

One thing to note, as demonstrated in the following diagram, is that only the PDFs that reside directly in the `reports` directory are copied:

.The effect of a flat filter on copying
image::copy-with-flat-filter-example.png[]

You can include files in subdirectories by using an Ant-style glob pattern (`\**/*`), as done in this updated example:

.Using a deep filter
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-multiple-files-with-deep-filter-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-multiple-files-with-deep-filter-example]"]
====

This task has the following effect:

.The effect of a deep filter on copying
image::copy-with-deep-filter-example.png[]

One thing to bear in mind is that a deep filter like this has the side effect of copying the directory structure below `reports` as well as the files. If you just want to copy the files without the directory structure, you need to use an explicit `fileTree(_dir_) { _includes_ }.files` expression. We talk more about the difference between file trees and file collections in the <<#sec:file_trees,File trees>> section.

This is just one of the variations in behavior you're likely to come across when dealing with file operations in Gradle builds. Fortunately, Gradle provides elegant solutions to almost all those use cases. Read the _in-depth_ sections later in the chapter for more detail on how the file operations work in Gradle and what options you have for configuring them.

[[sec:copying_directories_example]]
== Copying directory hierarchies

You may have a need to copy not just files, but the directory structure they reside in as well. This is the default behavior when you specify a directory as the `from()` argument, as demonstrated by the following example that copies everything in the `reports` directory, including all its subdirectories, to the destination:

.Copying an entire directory
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-directory-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-directory-example]"]
====

The key aspect that users struggle with is controlling how much of the directory structure goes to the destination. In the above example, do you get a `toArchive/reports` directory or does everything in `reports` go straight into `toArchive`? The answer is the latter. If a directory is part of the `from()` path, then it _won't_ appear in the destination.

So how do you ensure that `reports` itself is copied across, but not any other directory in `$buildDir`? The answer is to add it as an include pattern:

.Copying an entire directory, including itself
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-directory-including-itself-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-directory-including-itself-example]"]
====

You'll get the same behavior as before except with one extra level of directory in the destination, i.e. `toArchive/reports`.

One thing to note is how the `include()` directive applies only to the `from()`, whereas the directive in the previous section applied to the whole task.
These different levels of granularity in the copy specification allow you to easily handle most requirements that you will come across.
You can learn more about this in the section on <<sub:using_child_copy_specifications,child specifications>>.

[[sec:creating_archives_example]]
== Creating archives (zip, tar, etc.)

From the perspective of Gradle, packing files into an archive is effectively a copy in which the destination is the archive file rather than a directory on the file system. This means that creating archives looks a lot like copying, with all of the same features!

The simplest case involves archiving the entire contents of a directory, which this example demonstrates by creating a ZIP of the `toArchive` directory:

.Archiving a directory as a ZIP
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=create-archive-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=create-archive-example]"]
====

Notice how we specify the destination and name of the archive instead of an `into()`: both are required. You often won't see them explicitly set, because most projects apply the <<base_plugin.adoc#base_plugin,Base Plugin>>. It provides some conventional values for those properties. The next example demonstrates this and you can learn more about the conventions in the <<#sec:archive_naming,archive naming>> section.

Each type of archive has its own task type, the most common ones being link:{groovyDslPath}/org.gradle.api.tasks.bundling.Zip.html[Zip], link:{groovyDslPath}/org.gradle.api.tasks.bundling.Tar.html[Tar] and link:{groovyDslPath}/org.gradle.api.tasks.bundling.Jar.html[Jar]. They all share most of the configuration options of `Copy`, including filtering and renaming.

One of the most common scenarios involves copying files into specified subdirectories of the archive. For example, let's say you want to package all PDFs into a `docs` directory in the root of the archive. This `docs` directory doesn't exist in the source location, so you have to create it as part of the archive. You do this by adding an `into()` declaration for just the PDFs:

.Using the Base Plugin for its archive name convention
====
include::sample[dir="snippets/files/archivesWithBasePlugin/groovy",files="build.gradle[tags=create-archive-with-base-plugin-example]"]
include::sample[dir="snippets/files/archivesWithBasePlugin/kotlin",files="build.gradle.kts[tags=create-archive-with-base-plugin-example]"]
====

As you can see, you can have multiple `from()` declarations in a copy specification, each with its own configuration. See <<#sub:using_child_copy_specifications,Using child copy specifications>> for more information on this feature.

[[sec:unpacking_archives_example]]
== Unpacking archives

Archives are effectively self-contained file systems, so unpacking them is a case of copying the files from that file system onto the local file system — or even into another archive.
Gradle enables this by providing some wrapper functions that make archives available as hierarchical collections of files (<<sec:file_trees,file trees>>).

The two functions of interest are link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:zipTree(java.lang.Object)[Project.zipTree(java.lang.Object)] and link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:tarTree(java.lang.Object)[Project.tarTree(java.lang.Object)], which produce a link:{javadocPath}/org/gradle/api/file/FileTree.html[FileTree] from a corresponding archive file. That file tree can then be used in a `from()` specification, like so:

.Unpacking a ZIP file
====
include::sample[dir="snippets/files/archives/groovy",files="build.gradle[tags=unpack-archive-example]"]
include::sample[dir="snippets/files/archives/kotlin",files="build.gradle.kts[tags=unpack-archive-example]"]
====

As with a normal copy, you can control which files are unpacked via <<#sec:filtering_files,filters>> and even <<#sec:renaming_files,rename files>> as they are unpacked.

More advanced processing can be handled by the link:{groovyDslPath}/org.gradle.api.tasks.AbstractCopyTask.html#eachFile(org.gradle.api.Action)[eachFile()] method. For example, you might need to extract different subtrees of the archive into different paths within the destination directory. The following sample uses the method to extract the files within the archive's `libs` directory into the root destination directory, rather than into a `libs` subdirectory:

.Unpacking a subset of a ZIP file
====
include::sample[dir="snippets/files/archives/groovy",files="build.gradle[tags=unpack-archive-subset-example]"]
include::sample[dir="snippets/files/archives/kotlin",files="build.gradle.kts[tags=unpack-archive-subset-example]"]
====
<1> Extracts only the subset of files that reside in the `libs` directory
<2> Remaps the path of the extracting files into the destination directory by dropping the `libs` segment from the file path
<3> Ignores the empty directories resulting from the remapping, see Caution note below

[CAUTION]
====
You can not change the destination path of empty directories with this technique.
You can learn more in https://github.com/gradle/gradle/issues/2940[this issue].
====

If you're a Java developer and are wondering why there is no `jarTree()` method, that's because `zipTree()` works perfectly well for JARs, WARs and EARs.

[[sec:creating_uber_jar_example]]
== Creating "uber" or "fat" JARs

In the Java space, applications and their dependencies typically used to be packaged as separate JARs within a single distribution archive. That still happens, but there is another approach that is now common: placing the classes and resources of the dependencies directly into the application JAR, creating what is known as an uber or fat JAR.

Gradle makes this approach easy to accomplish. Consider the aim: to copy the contents of other JAR files into the application JAR. All you need for this is the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:zipTree(java.lang.Object)[Project.zipTree(java.lang.Object)] method and the link:{groovyDslPath}/org.gradle.api.tasks.bundling.Jar.html[Jar] task, as demonstrated by the `uberJar` task in the following example:

.Creating a Java uber or fat JAR
====
include::sample[dir="snippets/files/archivesWithJavaPlugin/groovy",files="build.gradle[tags=create-uber-jar-example]"]
include::sample[dir="snippets/files/archivesWithJavaPlugin/kotlin",files="build.gradle.kts[tags=create-uber-jar-example]"]
====

In this case, we're taking the runtime dependencies of the project — `configurations.runtimeClasspath.files` — and wrapping each of the JAR files with the `zipTree()` method. The result is a collection of ZIP file trees, the contents of which are copied into the uber JAR alongside the application classes.

[[sec:creating_directories_example]]
== Creating directories

Many tasks need to create directories to store the files they generate, which is why Gradle automatically manages this aspect of tasks when they explicitly define file and directory outputs. You can learn about this feature in the <<more_about_tasks.adoc#sec:up_to_date_checks,incremental build>> section of the user manual. All core Gradle tasks ensure that any output directories they need are created if necessary using this mechanism.

In cases where you need to create a directory manually, you can use the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:mkdir(java.lang.Object)[Project.mkdir(java.lang.Object)] method from within your build scripts or custom task implementations. Here's a simple example that creates a single `images` directory in the project folder:

.Manually creating a directory
====
include::sample[dir="snippets/files/misc/groovy",files="build.gradle[tags=mkdir-example]"]
include::sample[dir="snippets/files/misc/kotlin",files="build.gradle.kts[tags=mkdir-example]"]
====

As described in the {antManual}/Tasks/mkdir.html[Apache Ant manual], the `mkdir` task will automatically create all necessary directories in the given path and will do nothing if the directory already exists.

[[sec:moving_files_example]]
== Moving files and directories

Gradle has no API for moving files and directories around, but you can use the <<ant.adoc#ant,Apache Ant integration>> to easily do that, as shown in this example:

.Moving a directory using the Ant task
====
include::sample[dir="snippets/files/misc/groovy",files="build.gradle[tags=move-example]"]
include::sample[dir="snippets/files/misc/kotlin",files="build.gradle.kts[tags=move-example]"]
====

This is not a common requirement and should be used sparingly as you lose information and can easily break a build. It's generally preferable to copy directories and files instead.

[[sec:renaming_files_example]]
== Renaming files on copy

The files used and generated by your builds sometimes don't have names that suit, in which case you want to rename those files as you copy them. Gradle allows you to do this as part of a copy specification using the `rename()` configuration.

The following example removes the "-staging-" marker from the names of any files that have it:

.Renaming files as they are copied
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=rename-on-copy-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=rename-on-copy-example]"]
====

You can use regular expressions for this, as in the above example, or closures that use more complex logic to determine the target filename. For example, the following task truncates filenames:

.Truncating filenames as they are copied
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=truncate-names-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=truncate-names-example]"]
====

As with filtering, you can also apply renaming to a subset of files by configuring it as part of a child specification on a `from()`.

[[sec:deleting_files_example]]
== Deleting files and directories

You can easily delete files and directories using either the link:{groovyDslPath}/org.gradle.api.tasks.Delete.html[Delete] task or the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:delete(org.gradle.api.Action)[Project.delete(org.gradle.api.Action)] method.
In both cases, you specify which files and directories to delete in a way supported by the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:files(java.lang.Object++[]++)[Project.files(java.lang.Object...)] method.

For example, the following task deletes the entire contents of a build's output directory:

.Deleting a directory
====
include::sample[dir="snippets/files/misc/groovy",files="build.gradle[tags=delete-example]"]
include::sample[dir="snippets/files/misc/kotlin",files="build.gradle.kts[tags=delete-example]"]
====

If you want more control over which files are deleted, you can't use inclusions and exclusions in the same way as for copying files.
Instead, you have to use the builtin filtering mechanisms of `FileCollection` and `FileTree`.
The following example does just that to clear out temporary files from a source directory:

.Deleting files matching a specific pattern
====
include::sample[dir="snippets/files/misc/groovy",files="build.gradle[tags=delete-with-filter-example]"]
include::sample[dir="snippets/files/misc/kotlin",files="build.gradle.kts[tags=delete-with-filter-example]"]
====

You'll learn more about file collections and file trees in the next section.

[[sec:locating_files]]
== File paths in depth

In order to perform some action on a file, you need to know where it is, and that's the information provided by file paths. Gradle builds on the standard Java `{javaApi}/java/io/File.html[File]` class, which represents the location of a single file, and provides new APIs for dealing with collections of paths. This section shows you how to use the Gradle APIs to specify file paths for use in tasks and file operations.

But first, an important note on using hard-coded file paths in your builds.


[[sec:hard_coded_file_paths]]
=== On hard-coded file paths

Many examples in this chapter use hard-coded paths as string literals. This makes them easy to understand, but it's not good practice for real builds. The problem is that paths often change and the more places you need to change them, the more likely you are to miss one and break the build.

Where possible, you should use tasks, task properties, and <<writing_build_scripts.adoc#sec:extra_properties,project properties>> — in that order of preference — to configure file paths. For example, if you were to create a task that packages the compiled classes of a Java application, you should aim for something like this:

.How to minimize the number of hard-coded paths in your build
====
include::sample[dir="snippets/files/sampleJavaProject/groovy",files="build.gradle[tags=link-task-properties]"]
include::sample[dir="snippets/files/sampleJavaProject/kotlin",files="build.gradle.kts[tags=link-task-properties]"]
====

See how we're using the `compileJava` task as the source of the files to package and we've created a project property `archivesDirPath` to store the location where we put archives, on the basis we're likely to use it elsewhere in the build.

Using a task directly as an argument like this relies on it having <<more_about_tasks.adoc#sec:task_inputs_outputs,defined outputs>>, so it won't always be possible.
In addition, this example could be improved further by relying on the Java plugin's convention for `destinationDirectory` rather than overriding it, but it does demonstrate the use of project properties.

[[sec:single_file_paths]]
=== Single files and directories

Gradle provides the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:file(java.lang.Object)[Project.file(java.lang.Object)] method for specifying the location of a single file or directory.
Relative paths are resolved relative to the project directory, while absolute paths remain unchanged.

[CAUTION]
====
Never use `new File(relative path)` because this creates a path relative to the current working directory (CWD). Gradle can make no guarantees about the location of the CWD, which means builds that rely on it may break at any time.
====

Here are some examples of using the `file()` method with different types of argument:

.Locating files
====
include::sample[dir="snippets/files/file/groovy",files="build.gradle[tags=simple-params]"]
include::sample[dir="snippets/files/file/kotlin",files="build.gradle.kts[tags=simple-params]"]
====

As you can see, you can pass strings, `File` instances and `{javaApi}/java/nio/file/Path.html[Path]` instances to the `file()` method, all of which result in an absolute `File` object. You can find other options for argument types in the reference guide, linked in the previous paragraph.

What happens in the case of multi-project builds? The `file()` method will always turn relative paths into paths that are relative to the current project directory, which may be a child project. If you want to use a path that's relative to the _root project_ directory, then you need to use the special link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:rootDir[Project.getRootDir()] property to construct an absolute path, like so:

.Creating a path relative to a parent project
====
include::sample[dir="snippets/files/misc/groovy/project2",files="build.gradle[tags=using-root-dir-property]"]
include::sample[dir="snippets/files/misc/kotlin/project2",files="build.gradle.kts[tags=using-root-dir-property]"]
====

Let's say you're working on a multi-project build in a `dev/projects/AcmeHealth` directory. You use the above example in the build of the library you're fixing — at `AcmeHealth/subprojects/AcmePatientRecordLib/build.gradle`. The file path will resolve to the absolute version of `dev/projects/AcmeHealth/shared/config.xml`.

The `file()` method can be used to configure any task that has a property of type `File`. Many tasks, though, work on multiple files, so we look at how to specify sets of files next.

[[sec:file_collections]]
=== File collections

A _file collection_ is simply a set of file paths that's represented by the link:{javadocPath}/org/gradle/api/file/FileCollection.html[FileCollection] interface. _Any_ file paths.
It's important to understand that the file paths don't have to be related in any way, so they don't have to be in the same directory or even have a shared parent directory.
You will also find that many parts of the Gradle API use `FileCollection`, such as the copying API discussed later in this chapter and <<declaring_dependencies.adoc#sec:what-are-dependency-configurations,dependency configurations>>.

The recommended way to specify a collection of files is to use the link:{javadocPath}/org/gradle/api/file/ProjectLayout.html#files-java.lang.Object++...++-[ProjectLayout.files(java.lang.Object++...++)] method, which returns a `FileCollection` instance.
This method is very flexible and allows you to pass multiple strings, `File` instances, collections of strings, collections of ``File``s, and more.
You can even pass in tasks as arguments if they have <<more_about_tasks.adoc#sec:task_inputs_outputs,defined outputs>>.
Learn about all the supported argument types in the reference guide.

[CAUTION]
====
Although the `files()` method accepts `File` instances, never use `new File(relative path)` with it because this creates a path relative to the current working directory (CWD). Gradle can make no guarantees about the location of the CWD, which means builds that rely on it may break at any time.
====

As with the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:file(java.lang.Object)[Project.file(java.lang.Object)] method covered in the <<#sec:single_file_paths,previous section>>, all relative paths are evaluated relative to the current project directory. The following example demonstrates some of the variety of argument types you can use — strings, `File` instances, a list and a `{javaApi}/java/nio/file/Path.html[Path]`:

.Creating a file collection
====
include::sample[dir="snippets/files/fileCollections/groovy",files="build.gradle[tags=simple-params]"]
include::sample[dir="snippets/files/fileCollections/kotlin",files="build.gradle.kts[tags=simple-params]"]
====

File collections have some important attributes in Gradle. They can be:

 * created lazily
 * iterated over
 * filtered
 * combined

_Lazy creation_ of a file collection is useful when you need to evaluate the files that make up a collection at the time a build runs. In the following example, we query the file system to find out what files exist in a particular directory and then make those into a file collection:

.Implementing a file collection
====
include::sample[dir="snippets/files/fileCollections/groovy",files="build.gradle[tags=closure]"]
include::sample[dir="snippets/files/fileCollections/kotlin",files="build.gradle.kts[tags=closure]"]
====

.Output of **`gradle -q list`**
----
> gradle -q list
include::{snippetsPath}/files/fileCollections/tests/fileCollectionsWithClosure.out[]
----

The key to lazy creation is passing a closure (in Groovy) or a `Provider` (in Kotlin) to the `files()` method. Your closure/provider simply needs to return a value of a type accepted by `files()`, such as `List<File>`, `String`, `FileCollection`, etc.

_Iterating over a file collection_ can be done through the `each()` method (in Groovy) of `forEach` method (in Kotlin) on the collection or using the collection in a `for` loop. In both approaches, the file collection is treated as a set of `File` instances, i.e. your iteration variable will be of type `File`.

The following example demonstrates such iteration as well as how you can convert file collections to other types using the `as` operator or supported properties:

.Using a file collection
====
include::sample[dir="snippets/files/fileCollections/groovy",files="build.gradle[tags=usage]"]
include::sample[dir="snippets/files/fileCollections/kotlin",files="build.gradle.kts[tags=usage]"]
====

You can also see at the end of the example _how to combine file collections_ using the `+` and `-` operators to merge and subtract them. An important feature of the resulting file collections is that they are _live_. In other words, when you combine file collections in this way, the result always reflects what's currently in the source file collections, even if they change during the build.

For example, imagine `collection` in the above example gains an extra file or two after `union` is created. As long as you use `union` after those files are added to `collection`, `union` will also contain those additional files. The same goes for the `different` file collection.

Live collections are also important when it comes to _filtering_. If you want to use a subset of a file collection, you can take advantage of the link:{javadocPath}/org/gradle/api/file/FileCollection.html#filter-org.gradle.api.specs.Spec-[FileCollection.filter(org.gradle.api.specs.Spec)] method to determine which files to "keep". In the following example, we create a new collection that consists of only the files that end with .txt in the source collection:

.Filtering a file collection
====
include::sample[dir="snippets/files/fileCollections/groovy",files="build.gradle[tags=filtering-file-collections]"]
include::sample[dir="snippets/files/fileCollections/kotlin",files="build.gradle.kts[tags=filtering-file-collections]"]
====

.Output of **`gradle -q filterTextFiles`**
----
> gradle -q filterTextFiles
include::{snippetsPath}/files/fileCollections/tests/fileCollectionsFiltering.out[]
----

If `collection` changes at any time, either by adding or removing files from itself, then `textFiles` will immediately reflect the change because it is also a live collection. Note that the closure you pass to `filter()` takes a `File` as an argument and should return a boolean.

[[sec:file_trees]]
=== File trees

A _file tree_ is a file collection that retains the directory structure of the files it contains and has the type link:{javadocPath}/org/gradle/api/file/FileTree.html[FileTree]. This means that all the paths in a file tree must have a shared parent directory. The following diagram highlights the distinction between file trees and file collections in the common case of copying files:

.The differences in how file trees and file collections behave when copying files
image::file-collection-vs-file-tree.png[]

NOTE: Although `FileTree` extends `FileCollection` (an is-a relationship), their behaviors do differ. In other words, you can use a file tree wherever a file collection is required, but remember: a file collection is a flat list/set of files, while a file tree is a file and directory hierarchy. To convert a file tree to a flat collection, use the link:{javadocPath}/org/gradle/api/file/FileTree.html#getFiles--[FileTree.getFiles()] property.

The simplest way to create a file tree is to pass a file or directory path to the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:fileTree(java.lang.Object)[Project.fileTree(java.lang.Object)] method. This will create a tree of all the files and directories in that base directory (but not the base directory itself). The following example demonstrates how to use the basic method and, in addition, how to filter the files and directories using Ant-style patterns:

.Creating a file tree
====
include::sample[dir="snippets/files/fileTrees/groovy",files="build.gradle[tags=define]"]
include::sample[dir="snippets/files/fileTrees/kotlin",files="build.gradle.kts[tags=define]"]
====

You can see more examples of supported patterns in the API docs for link:{javadocPath}/org/gradle/api/tasks/util/PatternFilterable.html[PatternFilterable]. Also, see the API documentation for `fileTree()` to see what types you can pass as the base directory.

By default, `fileTree()` returns a `FileTree` instance that applies some default exclude patterns for convenience — the same defaults as Ant in fact. For the complete default exclude list, see http://ant.apache.org/manual/dirtasks.html#defaultexcludes[the Ant manual].

[[sec:change_default_excludes]]
If those default excludes prove problematic, you can workaround the issue by changing the default excludes in the settings script:

.Changing default excludes in the settings script
====
include::sample[dir="snippets/files/copy/groovy",files="settings.gradle[tags=change-default-exclusions]"]
include::sample[dir="snippets/files/copy/kotlin",files="settings.gradle.kts[tags=change-default-exclusions]"]
====

[NOTE]
====
Currently, Gradle's default excludes are configured via Ant's `DirectoryScanner` class.
====

[NOTE]
====
Gradle does not support changing default excludes during the execution phase.
====

You can do many of the same things with file trees that you can with file collections:

 * iterate over them (depth first)
 * filter them (using link:{javadocPath}/org/gradle/api/file/FileTree.html#matching-org.gradle.api.Action-[FileTree.matching(org.gradle.api.Action)] and Ant-style patterns)
 * merge them

You can also traverse file trees using the link:{javadocPath}/org/gradle/api/file/FileTree.html#visit-org.gradle.api.Action-[FileTree.visit(org.gradle.api.Action)] method. All of these techniques are demonstrated in the following example:

.Using a file tree
====
include::sample[dir="snippets/files/fileTrees/groovy",files="build.gradle[tags=use]"]
include::sample[dir="snippets/files/fileTrees/kotlin",files="build.gradle.kts[tags=use]"]
====

We've discussed how to create your own file trees and file collections, but it's also worth bearing in mind that many Gradle plugins provide their own instances of file trees, such as <<building_java_projects.adoc#sec:java_source_sets,Java's source sets>>. These can be used and manipulated in exactly the same way as the file trees you create yourself.

Another specific type of file tree that users commonly need is the archive, i.e. ZIP files, TAR files, etc. We look at those next.

[[sec:archive_contents]]
=== Using archives as file trees

An archive is a directory and file hierarchy packed into a single file. In other words, it's a special case of a file tree, and that's exactly how Gradle treats archives. Instead of using the `fileTree()` method, which only works on normal file systems, you use the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:zipTree(java.lang.Object)[Project.zipTree(java.lang.Object)] and link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:tarTree(java.lang.Object)[Project.tarTree(java.lang.Object)] methods to wrap archive files of the corresponding type (note that JAR, WAR and EAR files are ZIPs). Both methods return `FileTree` instances that you can then use in the same way as normal file trees. For example, you can extract some or all of the files of an archive by copying its contents to some directory on the file system. Or you can merge one archive into another.

Here are some simple examples of creating archive-based file trees:

.Using an archive as a file tree
====
include::sample[dir="snippets/files/fileTrees/groovy",files="build.gradle[tags=archive-trees]"]
include::sample[dir="snippets/files/fileTrees/kotlin",files="build.gradle.kts[tags=archive-trees]"]
====

You can see a practical example of extracting an archive file <<#sec:unpacking_archives_example,in among the common scenarios>> we cover.

[[sec:specifying_multiple_files]]
=== Understanding implicit conversion to file collections

Many objects in Gradle have properties which accept a set of input files.
For example, the link:{groovyDslPath}/org.gradle.api.tasks.compile.JavaCompile.html[JavaCompile] task has a `source` property that defines the source files to compile.
You can set the value of this property using any of the types supported by the <<#sec:file_collections,files()>> method, as mentioned in the api docs.
This means you can, for example, set the property to a `File`, `String`, collection, `FileCollection` or even a closure or `Provider`.

*This is a feature of specific tasks*!
That means implicit conversion will not happen for just any task that has a `FileCollection` or `FileTree` property.
If you want to know whether implicit conversion happens in a particular situation, you will need to read the relevant documentation, such as the corresponding task's API docs.
Alternatively, you can remove all doubt by explicitly using link:{javadocPath}/org/gradle/api/file/ProjectLayout.html#files-java.lang.Object++...++-[ProjectLayout.files(java.lang.Object++...++)] in your build.

Here are some examples of the different types of arguments that the `source` property can take:

.Specifying a set of files
====
include::sample[dir="snippets/files/inputFiles/groovy",files="build.gradle[tags=set-input-files]"]
include::sample[dir="snippets/files/inputFiles/kotlin",files="build.gradle.kts[tags=set-input-files]"]
====

One other thing to note is that properties like `source` have corresponding methods in core Gradle tasks. Those methods follow the convention of _appending_ to collections of values rather than replacing them. Again, this method accepts any of the types supported by the <<#sec:file_collections,files()>> method, as shown here:

.Appending a set of files
====
include::sample[dir="snippets/files/inputFiles/groovy",files="build.gradle[tags=add-input-files]"]
include::sample[dir="snippets/files/inputFiles/kotlin",files="build.gradle.kts[tags=add-input-files]"]
====

As this is a common convention, we recommend that you follow it in your own custom tasks. Specifically, if you plan to add a method to configure a collection-based property, make sure the method appends rather than replaces values.

[[sec:copying_files]]
== File copying in depth

The basic process of copying files in Gradle is a simple one:

 * Define a task of type link:{groovyDslPath}/org.gradle.api.tasks.Copy.html[Copy]
 * Specify which files (and potentially directories) to copy
 * Specify a destination for the copied files

But this apparent simplicity hides a rich API that allows fine-grained control of which files are copied, where they go, and what happens to them as they are copied — renaming of the files and token substitution of file content are both possibilities, for example.

Let's start with the last two items on the list, which form what is known as a _copy specification_. This is formally based on the link:{javadocPath}/org/gradle/api/file/CopySpec.html[CopySpec] interface, which the `Copy` task implements, and offers:

 * A link:{javadocPath}/org/gradle/api/file/CopySpec.html#from-java.lang.Object++...++-[CopySpec.from(java.lang.Object...)] method to define what to copy
 * An link:{javadocPath}/org/gradle/api/file/CopySpec.html#into-java.lang.Object-[CopySpec.into(java.lang.Object)] method to define the destination

`CopySpec` has several additional methods that allow you to control the copying process, but these two are the only required ones. `into()` is straightforward, requiring a directory path as its argument in any form supported by the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:file(java.lang.Object)[Project.file(java.lang.Object)] method. The `from()` configuration is far more flexible.

Not only does `from()` accept multiple arguments, it also allows several different types of argument. For example, some of the most common types are:

 * A `String` — treated as a file path or, if it starts with "file://", a file URI
 * A `File` — used as a file path
 * A `FileCollection` or `FileTree` — all files in the collection are included in the copy
 * A task — the files or directories that form a task's <<more_about_tasks.adoc#sec:task_inputs_outputs,defined outputs>> are included

In fact, `from()` accepts all the same arguments as link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:files(java.lang.Object++[]++)[Project.files(java.lang.Object...)] so see that method for a more detailed list of acceptable types.

Something else to consider is what type of thing a file path refers to:

 * A file — the file is copied as is
 * A directory — this is effectively treated as a file tree: everything in it, including subdirectories, is copied. However, the directory itself is not included in the copy.
 * A non-existent file — the path is ignored

Here is an example that uses multiple `from()` specifications, each with a different argument type. You will probably also notice that `into()` is configured lazily using a closure (in Groovy) or a Provider (in Kotlin) — a technique that also works with `from()`:

.Specifying copy task source files and destination directory
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-task-2]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-task-2]"]
====

Note that the lazy configuration of `into()` is different from a <<#sub:using_child_copy_specifications,child specification>>, even though the syntax is similar. Keep an eye on the number of arguments to distinguish between them.

[[filtering_files]]
=== Filtering files

You've already seen that you can filter file collections and file trees directly in a `Copy` task, but you can also apply filtering in any copy specification through the link:{javadocPath}/org/gradle/api/file/CopySpec.html#include-java.lang.String++...++-[CopySpec.include(java.lang.String...)] and link:{javadocPath}/org/gradle/api/file/CopySpec.html#exclude-java.lang.String++...++-[CopySpec.exclude(java.lang.String...)] methods.

Both of these methods are normally used with Ant-style include or exclude patterns, as described in link:{javadocPath}/org/gradle/api/tasks/util/PatternFilterable.html[PatternFilterable]. You can also perform more complex logic by using a closure that takes a link:{javadocPath}/org/gradle/api/file/FileTreeElement.html[FileTreeElement] and returns `true` if the file should be included or `false` otherwise. The following example demonstrates both forms, ensuring that only .html and .jsp files are copied, except for those .html files with the word "DRAFT" in their content:

.Selecting the files to copy
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-task-with-patterns]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-task-with-patterns]"]
====

A question you may ask yourself at this point is what happens when inclusion and exclusion patterns overlap? Which pattern wins? Here are the basic rules:

 * If there are no explicit inclusions or exclusions, everything is included
 * If at least one inclusion is specified, only files and directories matching the patterns are included
 * Any exclusion pattern overrides any inclusions, so if a file or directory matches at least one exclusion pattern, it won't be included, regardless of the inclusion patterns

Bear these rules in mind when creating combined inclusion and exclusion specifications so that you end up with the exact behavior you want.

Note that the inclusions and exclusions in the above example will apply to _all_ `from()` configurations. If you want to apply filtering to a subset of the copied files, you'll need to use <<sub:using_child_copy_specifications,child specifications>>.

[[sec:renaming_files]]
=== Renaming files

The <<#sec:renaming_files_example,example of how to rename files on copy>> gives you most of the information you need to perform this operation. It demonstrates the two options for renaming:

 * Using a regular expression
 * Using a closure

Regular expressions are a flexible approach to renaming, particularly as Gradle supports regex groups that allow you to remove and replaces parts of the source filename. The following example shows how you can remove the string "-staging-" from any filename that contains it using a simple regular expression:

.Renaming files as they are copied
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=rename-files]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=rename-files]"]
====

You can use any regular expression supported by the Java `{javaApi}/java/util/regex/Pattern.html[Pattern]` class and the substitution string (the second argument of `rename()` works on the same principles as the `{javaApi}/java/util/regex/Matcher.html#appendReplacement(java.lang.StringBuffer,%20java.lang.String)[Matcher.appendReplacement()]` method.

.Regular expressions in Groovy build scripts
[NOTE]
====
There are two common issues people come across when using regular expressions in this context:

 1. If you use a slashy string (those delimited by '/') for the first argument, you _must_ include the parentheses for `rename()` as shown in the above example.
 2. It's safest to use single quotes for the second argument, otherwise you need to escape the '$' in group substitutions, i.e. `"\$1\$2"`

The first is a minor inconvenience, but slashy strings have the advantage that you don't have to escape backslash ('\') characters in the regular expression. The second issue stems from Groovy's support for embedded expressions using `${ }` syntax in double-quoted and slashy strings.
====

The closure syntax for `rename()` is straightforward and can be used for any requirements that simple regular expressions can't handle. You're given the name of a file and you return a new name for that file, or `null` if you don't want to change the name. Do be aware that the closure will be executed for every file that's copied, so try to avoid expensive operations where possible.

[[sec:filtering_files]]
=== Filtering file content (token substitution, templating, etc.)

Not to be confused with filtering which files are copied, _file content filtering_ allows you to transform the content of files while they are being copied. This can involve basic templating that uses token substitution, removal of lines of text, or even more complex filtering using a full-blown template engine.

The following example demonstrates several forms of filtering, including token substitution using the link:{javadocPath}/org/gradle/api/file/CopySpec.html#expand-java.util.Map-[CopySpec.expand(java.util.Map)] method and another using link:{javadocPath}/org/gradle/api/file/CopySpec.html#filter-java.lang.Class-[CopySpec.filter(java.lang.Class)] with an https://ant.apache.org/manual/Types/filterchain.html[Ant filter]:

.Filtering files as they are copied
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=filter-files]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=filter-files]"]
====

The `filter()` method has two variants, which behave differently:

 * one takes a `{javaApi}/java/io/FilterReader.html[FilterReader]` and is designed to work with Ant filters, such as `ReplaceTokens`
 * one takes a closure or link:{javadocPath}/org/gradle/api/Transformer.html[Transformer] that defines the transformation for each line of the source file

Note that both variants assume the source files are text based. When you use the `ReplaceTokens` class with `filter()`, the result is a template engine that replaces tokens of the form `@tokenName@` (the Ant-style token) with values that you define.

The `expand()` method treats the source files as https://docs.groovy-lang.org/latest/html/api/groovy/text/SimpleTemplateEngine.html[Groovy templates], which evaluate and expand expressions of the form `${expression}`. You can pass in property names and values that are then expanded in the source files. `expand()` allows for more than basic token substitution as the embedded expressions are full-blown Groovy expressions.

NOTE: It's good practice to specify the character set when reading and writing the file, otherwise the transformations won't work properly for non-ASCII text. You configure the character set with the link:{javadocPath}/org/gradle/api/file/CopySpec.html#getFilteringCharset--[CopySpec.getFilteringCharset()] property. If it's not specified, the JVM default character set is used, which is likely to be different from the one you want.

[[sec:using_the_copyspec_class]]
=== Using the `CopySpec` class

A copy specification (or copy spec for short) determines what gets copied to where, and what happens to files during the copy. You've alread seen many examples in the form of configuration for `Copy` and archiving tasks. But copy specs have two attributes that are worth covering in more detail:

 1. They can be independent of tasks
 2. They are hierarchical

The first of these attributes allows you to _share copy specs within a build_. The second provides fine-grained control within the overall copy specification.

[[sub:sharing_copy_specs]]
==== Sharing copy specs

Consider a build that has several tasks that copy a project's static website resources or add them to an archive. One task might copy the resources to a folder for a local HTTP server and another might package them into a distribution. You could manually specify the file locations and appropriate inclusions each time they are needed, but human error is more likely to creep in, resulting in inconsistencies between tasks.

One solution Gradle provides is the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:copySpec(org.gradle.api.Action)[Project.copySpec(org.gradle.api.Action)] method. This allows you to create a copy spec outside of a task, which can then be attached to an appropriate task using the link:{javadocPath}/org/gradle/api/file/CopySpec.html#with-org.gradle.api.file.CopySpec++...++-[CopySpec.with(org.gradle.api.file.CopySpec...)] method. The following example demonstrates how this is done:

.Sharing copy specifications
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=standalone-copyspec]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=standalone-copyspec]"]
====

Both the `copyAssets` and `distApp` tasks will process the static resources under `src/main/webapp`, as specified by `webAssetsSpec`.

[NOTE]
====
The configuration defined by `webAssetsSpec` will _not_ apply to the app classes included by the `distApp` task. That's because `from appClasses` is its own child specification independent of `with webAssetsSpec`.

This can be confusing to understand, so it's probably best to treat `with()` as an extra `from()` specification in the task. Hence it doesn't make sense to define a standalone copy spec without at least one `from()` defined.
====

If you encounter a scenario in which you want to apply the same copy configuration to _different_ sets of files, then you can share the configuration block directly without using `copySpec()`. Here's an example that has two independent tasks that happen to want to process image files only:

.Sharing copy patterns only
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=shared-copy-patterns]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=shared-copy-patterns]"]
====

In this case, we assign the copy configuration to its own variable and apply it to whatever `from()` specification we want. This doesn't just work for inclusions, but also exclusions, file renaming, and file content filtering.

[[sub:using_child_copy_specifications]]
==== Using child specifications

If you only use a single copy spec, the file filtering and renaming will apply to _all_ the files that are copied. Sometimes this is what you want, but not always. Consider the following example that copies files into a directory structure that can be used by a Java Servlet container to deliver a website:

.Creating an exploded WAR for a Servlet container
image::exploded-war-child-copy-spec-example.png[]

This is not a straightforward copy as the `WEB-INF` directory and its subdirectories don't exist within the project, so they must be created during the copy. In addition, we only want HTML and image files going directly into the root folder — `build/explodedWar` — and only JavaScript files going into the `js` directory. So we need separate filter patterns for those two sets of files.

The solution is to use _child specifications_, which can be applied to both `from()` and `into()` declarations. The following task definition does the necessary work:

.Nested copy specs
====
include::sample[dir="snippets/files/sampleJavaProject/groovy",files="build.gradle[tags=nested-specs]"]
include::sample[dir="snippets/files/sampleJavaProject/kotlin",files="build.gradle.kts[tags=nested-specs]"]
====

Notice how the `src/dist` configuration has a nested inclusion specification: that's the child copy spec. You can of course add content filtering and renaming here as required. A child copy spec is still a copy spec.

The above example also demonstrates how you can copy files into a subdirectory of the destination either by using a child `into()` on a `from()` or a child `from()` on an `into()`. Both approaches are acceptable, but you may want to create and follow a convention to ensure consistency across your build files.

[NOTE]
Don't get your `into()` specifications mixed up! For a normal copy — one to the filesystem rather than an archive — there should always be _one_ "root" `into()` that simply specifies the overall destination directory of the copy. Any other `into()` should have a child spec attached and its path will be relative to the root `into()`.

One final thing to be aware of is that a child copy spec inherits its destination path, include patterns, exclude patterns, copy actions, name mappings and filters from its parent. So be careful where you place your configuration.

[[sec:project_copy_method]]
=== Copying files in your own tasks

There might be occasions when you want to copy files or directories as _part_ of a task. For example, a custom archiving task based on an unsupported archive format might want to copy files to a temporary directory before they are then archived. You still want to take advantage of Gradle's copy API, but without introducing an extra `Copy` task.

The solution is to use the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:copy(org.gradle.api.Action)[Project.copy(org.gradle.api.Action)] method. It works the same way as the `Copy` task by configuring it with a copy spec. Here's a trivial example:

.Copying files using the copy() method without up-to-date check
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-method]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-method]"]
====

The above example demonstrates the basic syntax and also highlights two major limitations of using the `copy()` method:

 1. The `copy()` method is not <<more_about_tasks.adoc#sec:up_to_date_checks,incremental>>. The example's `copyMethod` task will _always_ execute because it has no information about what files make up the task's inputs. You have to manually define the task inputs and outputs.

 2. Using a task as a copy source, i.e. as an argument to `from()`, won't set up an automatic task dependency between your task and that copy source. As such, if you are using the `copy()` method as part of a task action, you must explicitly declare all inputs and outputs in order to get the correct behavior.

The following example shows you how to workaround these limitations by using the <<more_about_tasks.adoc#sec:task_input_output_runtime_api,dynamic API for task inputs and outputs>>:

.Copying files using the copy() method with up-to-date check
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=copy-method-with-dependency]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=copy-method-with-dependency]"]
====

These limitations make it preferable to use the `Copy` task wherever possible, because of its builtin support for incremental building and task dependency inference. That is why the `copy()` method is intended for use by <<custom_tasks.adoc#custom_tasks,custom tasks>> that need to copy files as part of their function. Custom tasks that use the `copy()` method should declare the necessary inputs and outputs relevant to the copy action.

[[sec:sync_task]]
=== Mirroring directories and file collections with the `Sync` task

The link:{groovyDslPath}/org.gradle.api.tasks.Sync.html[Sync] task, which extends the `Copy` task, copies the source files into the destination directory and then removes any files from the destination directory which it did not copy. In other words, it synchronizes the contents of a directory with its source. This can be useful for doing things such as installing your application, creating an exploded copy of your archives, or maintaining a copy of the project's dependencies.

Here is an example which maintains a copy of the project's runtime dependencies in the `build/libs` directory.

.Using the Sync task to copy dependencies
====
include::sample[dir="snippets/files/sync/groovy",files="build.gradle[tags=copy-dependencies]"]
include::sample[dir="snippets/files/sync/kotlin",files="build.gradle.kts[tags=copy-dependencies]"]
====

You can also perform the same function in your own tasks with the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:sync(org.gradle.api.Action)[Project.sync(org.gradle.api.Action)] method.

[[sec:archives]]
== Archive creation in depth

Archives are essentially self-contained file systems and Gradle treats them as such. This is why working with archives is very similar to working with files and directories, including such things as file permissions.

Out of the box, Gradle supports creation of both ZIP and TAR archives, and by extension Java's JAR, WAR and EAR formats — Java's archive formats are all ZIPs. Each of these formats has a corresponding task type to create them: link:{groovyDslPath}/org.gradle.api.tasks.bundling.Zip.html[Zip], link:{groovyDslPath}/org.gradle.api.tasks.bundling.Tar.html[Tar], link:{groovyDslPath}/org.gradle.api.tasks.bundling.Jar.html[Jar], link:{groovyDslPath}/org.gradle.api.tasks.bundling.War.html[War], and link:{groovyDslPath}/org.gradle.plugins.ear.Ear.html[Ear]. These all work the same way and are based on copy specifications, just like the `Copy` task.

Creating an archive file is essentially a file copy in which the destination is implicit, i.e. the archive file itself. Here's a basic example that specifies the path and name of the target archive file:

.Archiving a directory as a ZIP
====
include::sample[dir="snippets/files/copy/groovy",files="build.gradle[tags=create-archive-example]"]
include::sample[dir="snippets/files/copy/kotlin",files="build.gradle.kts[tags=create-archive-example]"]
====

In the next section you'll learn about convention-based archive names, which can save you from always configuring the destination directory and archive name.

The full power of copy specifications are available to you when creating archives, which means you can do content filtering, file renaming or anything else that is covered in the previous section. A particularly common requirement is copying files into subdirectories of the archive that don't exist in the source folders, something that can be achieved with `into()` <<#sub:using_child_copy_specifications,child specifications>>.

Gradle does of course allow you create as many archive tasks as you want, but it's worth bearing in mind that many convention-based plugins provide their own. For example, the Java plugin adds a `jar` task for packaging a project's compiled classes and resources in a JAR. Many of these plugins provide sensible conventions for the names of archives as well as the copy specifications used. We recommend you use these tasks wherever you can, rather than overriding them with your own.

[[sec:archive_naming]]
=== Archive naming

Gradle has several conventions around the naming of archives and where they are created based on the plugins your project uses. The main convention is provided by the <<base_plugin.adoc#base_plugin,Base Plugin>>, which defaults to creating archives in the `$buildDir/distributions` directory and typically uses archive names of the form _[projectName]-[version].[type]_.

The following example comes from a project named `archive-naming`, hence the `myZip` task creates an archive named `archive-naming-1.0.zip`:

.Creation of ZIP archive
====
include::sample[dir="snippets/files/archiveNaming/groovy",files="build.gradle[tags=zip-task]"]
include::sample[dir="snippets/files/archiveNaming/kotlin",files="build.gradle.kts[tags=zip-task]"]
====

.Output of **`gradle -q myZip`**
----
> gradle -q myZip
include::{snippetsPath}/files/archiveNaming/tests/archiveNaming.out[]
----

Note that the name of the archive does _not_ derive from the name of the task that creates it.

If you want to change the name and location of a generated archive file, you can provide values for the `archiveFileName` and `destinationDirectory` properties of the corresponding task.
These override any conventions that would otherwise apply.

Alternatively, you can make use of the default archive name pattern provided by link:{groovyDslPath}/org.gradle.api.tasks.bundling.AbstractArchiveTask.html#org.gradle.api.tasks.bundling.AbstractArchiveTask:archiveFileName[AbstractArchiveTask.getArchiveFileName()]: _[archiveBaseName]-[archiveAppendix]-[archiveVersion]-[archiveClassifier].[archiveExtension]_.
You can set each of these properties on the task separately if you wish.
Note that the Base Plugin uses the convention of project name for _archiveBaseName_, project version for _archiveVersion_ and the archive type for _archiveExtension_.
It does not provide values for the other properties.

This example — from the same project as the one above — configures just the `archiveBaseName` property, overriding the default value of the project name:

.Configuration of archive task - custom archive name
====
include::sample[dir="snippets/files/archiveNaming/groovy",files="build.gradle[tags=zip-task-with-custom-base-name]"]
include::sample[dir="snippets/files/archiveNaming/kotlin",files="build.gradle.kts[tags=zip-task-with-custom-base-name]"]
====

.Output of **`gradle -q myCustomZip`**
----
> gradle -q myCustomZip
include::{snippetsPath}/files/archiveNaming/tests/zipWithCustomName.out[]
----

You can also override the default `archiveBaseName` value for _all_ the archive tasks in your build by using the _project_ property `archivesBaseName`, as demonstrated by the following example:

.Configuration of archive task - appendix &amp; classifier
====
include::sample[dir="snippets/files/archivesChangedBaseName/groovy",files="build.gradle[]"]
include::sample[dir="snippets/files/archivesChangedBaseName/kotlin",files="build.gradle.kts[]"]
====

.Output of **`gradle -q echoNames`**
----
> gradle -q echoNames
include::{snippetsPath}/files/archivesChangedBaseName/tests/zipWithArchivesBaseName.out[]
----

You can find all the possible archive task properties in the API documentation for link:{groovyDslPath}/org.gradle.api.tasks.bundling.AbstractArchiveTask.html[AbstractArchiveTask], but we have also summarized the main ones here:

`archiveFileName` — `Property<String>`, default: `__archiveBaseName__-__archiveAppendix__-__archiveVersion__-__archiveClassifier__.__archiveExtension__`::
The complete file name of the generated archive. If any of the properties in the default value are empty, their '-' separator is dropped.

`archiveFile` — `Provider<RegularFile>`, _read-only_, default: `__destinationDirectory__/__archiveFileName__`::
The absolute file path of the generated archive.

`destinationDirectory` — `DirectoryProperty`, default: depends on archive type::
The target directory in which to put the generated archive. By default, JARs and WARs go into `$buildDir/libs`. ZIPs and TARs go into `$buildDir/distributions`.

`archiveBaseName` — `Property<String>`, default: `__project.name__`::
The base name portion of the archive file name, typically a project name or some other descriptive name for what it contains.

`archiveAppendix` — `Property<String>`, default: `null`::
The appendix portion of the archive file name that comes immediately after the base name. It is typically used to distinguish between different forms of content, such as code and docs, or a minimal distribution versus a full or complete one.

`archiveVersion` — `Property<String>`, default: `__project.version__`::
The version portion of the archive file name, typically in the form of a normal project or product version.

`archiveClassifier` — `Property<String>`, default: `null`::
The classifier portion of the archive file name. Often used to distinguish between archives that target different platforms.

`archiveExtension` — `Property<String>`, default: depends on archive type and compression type::
The filename extension for the archive. By default, this is set based on the archive task type and the compression type (if you're creating a TAR). Will be one of: `zip`, `jar`, `war`, `tar`, `tgz` or `tbz2`. You can of course set this to a custom extension if you wish.

[[sec:sharing_content_between_multiple_archives]]
=== Sharing content between multiple archives

<<#sub:sharing_copy_specs,As described earlier>>, you can use the link:{groovyDslPath}/org.gradle.api.Project.html#org.gradle.api.Project:copySpec(org.gradle.api.Action)[Project.copySpec(org.gradle.api.Action)] method to share content between archives.

[[sec:reproducible_archives]]
=== Reproducible builds

Sometimes it's desirable to recreate archives exactly the same, byte for byte, on different machines. You want to be sure that building an artifact from source code produces the same result no matter when and where it is built. This is necessary for projects like https://reproducible-builds.org/[reproducible-builds.org].

Reproducing the same byte-for-byte archive poses some challenges since the order of the files in an archive is influenced by the underlying file system. Each time a ZIP, TAR, JAR, WAR or EAR is built from source, the order of the files inside the archive may change. Files that only have a different timestamp also causes differences in archives from build to build. All link:{groovyDslPath}/org.gradle.api.tasks.bundling.AbstractArchiveTask.html[AbstractArchiveTask] (e.g. Jar, Zip) tasks shipped with Gradle include support for producing reproducible archives.

For example, to make a `Zip` task reproducible you need to set link:{groovyDslPath}/org.gradle.api.tasks.bundling.Zip.html#org.gradle.api.tasks.bundling.Zip:reproducibleFileOrder[Zip.isReproducibleFileOrder()] to `true` and link:{groovyDslPath}/org.gradle.api.tasks.bundling.Zip.html#org.gradle.api.tasks.bundling.Zip:preserveFileTimestamps[Zip.isPreserveFileTimestamps()] to `false`. In order to make all archive tasks in your build reproducible, consider adding the following configuration to your build file:

.Activating reproducible archives
====
include::sample[dir="snippets/files/archives/groovy",files="build.gradle[tags=reproducible]"]
include::sample[dir="snippets/files/archives/kotlin",files="build.gradle.kts[tags=reproducible]"]
====

Often you will want to publish an archive, so that it is usable from another project.
This process is described in <<cross_project_publications.adoc#cross_project_publications,Cross-Project publications>>.
