Reputation: 5236
I have two directory trees:
source/aaa/bbb/ccc/file01.txt
source/aaa/bbb/file02.txt
source/aaa/bbb/file03.txt
source/aaa/ddd/file03.txt
source/file01.txt
and
template/aaa/bbb/ccc/file01.txt
template/aaa/bbb/DELETE-file03.txt
template/aaa/DELETE-ddd
template/DELETE-file01.txt
Using Ant, I want to do three things. First, I want to copy any files from "template" into "source", such that all files not starting with "DELETE-" are replaced. For example, "source/aaa/bbb/ccc/file01.txt" would be replaced. This is straightforward with:
<copy todir="source" verbose="true" overwrite="true">
<fileset dir="template">
<exclude name="**/DELETE-*"/>
</fileset>
</copy>
Second, I want to delete all files in the "source" tree whose name matches a "DELETE-" file in the corresponding directory of the "template" tree. For example, both "source/aaa/bbb/file03.txt" and "source/file01.txt" will be deleted. I have been able to accomplish this with:
<delete verbose="true">
<fileset dir="source">
<present present="both" targetdir="template">
<mapper type="regexp" from="(.*[/\\])?([^/\\]+)" to="\1DELETE-\2"/>
</present>
</fileset>
</delete>
Third, I'd like to delete any directories (empty or not) whose names match in the same way. For example, "template/aaa/DELETE-ddd" and all file(s) under it would be deleted. I'm not sure how to construct a fileset that matches directories (and all the files under them) in the "source" tree where the directory has a DELETE-* file in the "template" tree.
Is this third task even possible with Ant (1.7.1)? I'd preferrably like to do this without writing any custom ant tasks/selectors.
Upvotes: 1
Views: 2081
Reputation: 5236
It seems the root issue that makes this difficult is that ant drives selectors/filesets based on files found within the target directory of fileset. Normally, however, one would want to drive things from the list of DELETE-* marker files.
The best solution I've found so far does require some custom code. I chose the <groovy>
task, but also could have used <script>
.
The gist: create a fileset, use groovy to add a series of excludes that skip files and directories with a DELETE-* marker, then perform the copy. This accomplishes the second and third task from my question.
<fileset id="source_files" dir="source"/>
<!-- add exclude patterns to fileset that will skip any files with a DELETE-* marker -->
<groovy><![CDATA[
def excludes = []
new File( "template" ).eachFileRecurse(){ File templateFile ->
if( templateFile.name =~ /DELETE-*/ ){
// file path relative to template dir
def relativeFile = templateFile.toString().substring( "template".length() )
// filename with DELETE- prefix removed
def withoutPrefix = relativeFile.replaceFirst( "DELETE-", "")
// add wildcard to match all files under directories
def exclude = withoutPrefix + "/**"
excludes << exclude
}
}
def fileSet = project.getReference("source_files")
fileSet.appendExcludes(excludes as String[])
]]></groovy>
<!-- create a baseline copy, excluding files with DELETE-* markers in the template directories -->
<copy todir="target">
<fileset refid="source_files"/>
</copy>
Upvotes: 1
Reputation: 10377
To delete a directory and its contents use delete with nested fileset
, i.e. :
<delete includeemptydirs="true">
<fileset dir="your/root/directory" defaultexcludes="false">
<include name="**/DELETE-*/**" />
</fileset>
</delete>
With attribute includeemptydirs="true"
the directories will be deleted too.
Upvotes: 0