Maven Clean: excluding directory inside target from being deleted

10.6k Views Asked by At

I have tried many variants but could not make this work. One example (child pom.xml):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-clean-plugin</artifactId>
    <configuration>
        <filesets>
            <fileset>
                <directory>target</directory>
                <useDefaultExcludes>true</useDefaultExcludes>
                <excludes>
                    <exclude>myFolder</exclude>
                </excludes>
            </fileset>
        </filesets>
    </configuration>
</plugin>

Maven always tries to delete my folder. Why?

3

There are 3 best solutions below

4
On BEST ANSWER

As also suggested by @AR.3 in the answer here, the clean phase and goal would -

By default, it discovers and deletes the directories configured in project.build.directory, project.build.outputDirectory, project.build.testOutputDirectory, and project.reporting.outputDirectory.

Still, if you want to exclude a specific folder from being deleted you can follow the inverse approach(a simple hack) to do it as follows -

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-clean-plugin</artifactId>
       <version>3.0.0</version>
       <configuration>
           <excludeDefaultDirectories>true</excludeDefaultDirectories>
           <filesets>
                <fileset>
                    <directory>target</directory>
                    <followSymlinks>false</followSymlinks>
                    <useDefaultExcludes>true</useDefaultExcludes>
                    <includes>
                          <include><!--everything other that what you want to exclude--></include>
                    </includes>
                 </fileset>
            </filesets>
        </configuration>
</plugin>

More about excludeDefaultDirectories from a similar link -

Disables the deletion of the default output directories configured for a project. If set to true, only the files/directories selected via the parameter filesets will be deleted.

EDIT

It is indeed possible to exclude a specific folder from being deleted using a direct approach:

<configuration>
    <excludeDefaultDirectories>true</excludeDefaultDirectories>
        <filesets>
            <fileset>
                <directory>target</directory>
                <includes>
                    <include>**</include>
                </includes>
                <excludes>
                    <exclude><!-- folder to exclude --></exclude>
                </excludes>
            </fileset>
        </filesets>
</configuration>
0
On

Per the comment by @Christian, this solution uses a profile to determine whether or not to let maven-clean delete the excluded folder (and subfolders with /**). In my use case, a process generates parser source files in target/generated-sources prior to compilation. I usually want to keep them to save time. I'm also lazy (like most of us developers) and don't like to type. Commands to build the project:

  1. Profile inactive, keep the parser source: mvn clean install
  2. Profile activated, really, truly clean: mvn clean install delete-parsers

The code:

<properties>
    <!-- By default, clean will skip the parser source files
         generated in this folder and its subfolders.  -->
    <skip.parser.source>generated-sources/**</skip.parser.source>
</properties>

<profiles>
    <!-- Activate this profile to delete parser sources. -->
    <profile>
        <id>delete-parsers</id>
        <!-- Setting this property to null removes the exclusion 
             in maven-clean.  -->
        <properties>
            <skip.parser.source />
        </properties>
    </profile>
</profiles>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
    <!-- Required so maven standard folders won't be deleted. -->
    <excludeDefaultDirectories>true</excludeDefaultDirectories>
    <filesets>
        <fileset>
            <!-- Delete everything in target/** -->
            <directory>target</directory>
            <includes>
                <include>**</include>
            </includes>
            <!-- But NOT this folder when the profile is activated. -->
            <excludes>
                <exclude>${skip.parser.source}</exclude>
            </excludes>
        </fileset>
    </filesets>
</configuration>
2
On

From the documentation of the clean:clean goal:

This attempts to clean a project's working directory of the files that were generated at build-time. By default, it discovers and deletes the directories configured in project.build.directory, project.build.outputDirectory, project.build.testOutputDirectory, and project.reporting.outputDirectory.

Files outside the default may also be included in the deletion by configuring the filesets tag.

This means that whatever you declare in the filesets element, the target directory will always be deleted (EDIT unless excludeDefaultDirectories is set to true, see below edit). Given the above description, a workaround is to do the following:

  1. Temporarily override the above properties to point to something other than the default target directory, before cleaning the directories.

  2. Use the filesets mechanism to tell which directories to exclude from the target directory (same as what you already did).

  3. Restore the properties after cleaning the directories.

The pre-clean and post-clean lifecycle phases can be used to do steps 1 and 3.

EDIT: (thanks to nullpointer for pointing it out)

Setting the goal parameter excludeDefaultDirectories to true will exclude the default directory from being deleted, in which case you can use the filesets approach without the hack of overriding the Maven properties.