2014-03-25 104 views
1

我有一個包含多個子目錄的目錄。裏面有文件。在這些file1.ext之外是在一個以上的目錄中存在重複。子目錄和文件名在執行時顯然是未知的。Ant:如何停止複製副本

 
-> 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> 

這工作正常,並達到我想要的結果,但是,在bigdir中有重複文件是錯誤的。我想構建失敗,如果它檢測到bigdir有重複的文件名

我試圖找到一種方法,使<copy>任務失敗,在這種情況下。它不一定要通過這種方法。如果我能弄明白,我也可以在複製之前愉快地在目錄上運行某種validation

也許會使每個複製文件爲只讀,以便後續覆蓋作爲copy flatten=true的結果未能覆蓋併產生錯誤?

沒有螞蟻的contrib請

回答

1

您可以使用scriptcondition(見ant manual conditions),帶有內置的JavaScript引擎 (因爲Java的06年6月1日包括在內,所以沒有額外的庫或螞蟻插件需要),這樣的:

<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 

順便說一下,往往是更易於使用的API螞蟻:

// get DirectoryScanner 
ds = whatever.getDirectoryScanner(project); 
// get the included files => array 
checkFiles = ds.getIncludedFiles(); 

instea d的:

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); 
} 

正如我在第一個片段中使用的。

+0

謝謝你,工作。確實在尋找更多的「原生」解決方案,但仍然是很好的答案。 – Slav

+0

如何顯示哪些文件是重複的? @Rebse – Slav