我有一个包含多个子目录的目录。里面有文件。其中file1.ext
是多个目录中的重复项。子目录和文件名在执行时显然是未知的。
-> bigdir --------> subdir1 ----------------> file1.ext --------> subdir2 ----------------> file1.ext --------> subdir3 ----------------> file2.ext
我正在尝试使用 bigdir
将smalldir
的内容复制到flatten="true"
,以便我的结果文件结构如下所示
-> smalldir ----------> file1.ext ----------> file2.ext
到目前为止,我有以下
<copy todir="${smalldir}" flatten="true" verbose="true">
<fileset dir="${bigdir}">
<include name="**/*.ext"/>
</fileset>
</copy>
这样可以正常运行并达到我想要的结果 HOWEVER ,在bigdir
中包含重复文件是错误的。如果检测到bigdir
在
在这种情况下,我试图找到一种方法使<copy>
任务失败。它不一定要通过这种方法。如果我能弄清楚如何,我也可以在复制之前在目录上运行某种validation
。
也许将每个复制的文件设为只读,以便copy flatten=true
导致的后续覆盖无法覆盖并产生错误?
请不要使用ant-contrib
答案 0 :(得分:1)
您可以使用内置javascript引擎的scriptcondition(请参阅ant manual conditions)
(自Java 1.6.06起包含,因此不需要额外的库或蚂蚁插件),如下所示:
<project>
<fileset dir="C:\tmp\bigdir" id="whatever"/>
<echo>${toString:whatever}</echo>
<fail message="Duplicate Filenames detected !!">
<condition>
<scriptcondition language="javascript">
<![CDATA[
importPackage(java.util);
var input = project.getProperty('toString:whatever').split(';');
// get basenames
for (var i = 0; i < input.length; i++) {
input[i]=input[i].substring(input[i].lastIndexOf("\\")+1);
}
var inputList = Arrays.asList(input);
// no duplicates in Hashset
var inputSet = new HashSet(inputList);
self.setValue(inputSet.size() < inputList.size());
]]>
</scriptcondition>
</condition>
</fail>
</project>
输出:
[echo] subdir1\foo.txt;subdir2\foo.txt;subdir3\foobar.txt
BUILD FAILED
C:\area51\AntTest\tryme.xml:7: Duplicate Filenames detected !!
- 评论后编辑 -
要显示重复项,请使用以下内容:
<project>
<fileset dir="C:\bigdir" id="whatever"/>
<echo>${toString:whatever}</echo>
<fail message="Duplicate Filenames detected !!">
<condition>
<scriptcondition language="javascript">
<![CDATA[
importPackage(java.util);
// get DirectoryScanner
ds = whatever.getDirectoryScanner(project);
// get the included files => array
checkFiles = ds.getIncludedFiles();
var checkSet = new HashSet();
var s = "";
for (j=0; j < checkFiles.length; j++) {
f = new java.io.File(whatever.getDir(project), checkFiles[j]);
if(!checkSet.add(f.getName()))
s += f + '\n';
}
println(s.substring(0, s.length - 1));
self.setValue(checkSet.size() < checkFiles.length);
]]>
</scriptcondition>
</condition>
</fail>
</project>
输出:
[echo] subdir1\foo.txt;subdir2\foo.txt;subdir3\foobar.txt;subdir3\subsubdir1\foo.txt;subdir3\subsubdir2\foobar.txt;subdir4\foobaz.txt
[fail] C:\bigdir\subdir2\foo.txt
[fail] C:\bigdir\subdir3\subsubdir1\foo.txt
[fail] C:\bigdir\subdir3\subsubdir2\foobar.txt
BUILD FAILED
顺便说一句,使用ant api通常要简单得多:// get DirectoryScanner
ds = whatever.getDirectoryScanner(project);
// get the included files => array
checkFiles = ds.getIncludedFiles();
而不是:
var input = project.getProperty('toString:whatever').split(';');
// get basenames
for (var i = 0; i < input.length; i++) {
input[i]=input[i].substring(input[i].lastIndexOf("\\")+1);
}
正如我在第一个片段中使用的那样。