2011-09-23 57 views
3

我想几个zip文件一起使用ANT结合,但我已经有三个限制,导致标准技术失败:结合ZIP档案中ant与过滤和案例sensativity

  1. 有文件(已知的文件名),我不想包含在最终的档案中。
  2. 一些源档案包含名称相同,但大小写不同的文件。
  3. 运行脚本的机器使用不区分大小写的文件系统。

为了使我的问题具体,这里有一个例子源存档。我做不是知道a.txtA.txt代表的文件名,但是我的做的知道文件名b.txt

$ touch a.txt ; zip src.zip a.txt ; rm a.txt 
$ touch A.txt ; zip src.zip A.txt ; rm A.txt 
$ touch b.txt ; zip src.zip b.txt ; rm b.txt 
$ unzip -l src.zip 
Archive: src.zip 
    Length  Date Time Name 
-------- ---- ---- ---- 
     0 09-23-11 11:35 a.txt 
     0 09-23-11 11:35 A.txt 
     0 09-23-11 11:36 b.txt 
--------     ------- 
     0     3 files 

这里就是我想要的:(一切从原来的档案,除了b.txt)

$ ant 
$ unzip -l expected.zip 
Archive: expected.zip 
    Length  Date Time Name 
-------- ---- ---- ---- 
     0 09-23-11 11:35 a.txt 
     0 09-23-11 11:35 A.txt 
--------     ------- 
     0     2 files 

我发现建议在互联网上的两种技术:

<target name="unzip-then-rezip"> 
    <!-- Either a.txt or A.txt is lost during unzip and 
     does not appear in out.zip --> 
    <delete dir="tmp"/> 
    <delete file="out.zip"/> 
    <mkdir dir="tmp"/> 
    <unzip src="src.zip" dest="tmp"/> 
    <zip destfile="out.zip" basedir="tmp" excludes="b.txt"/> 
</target> 

<target name="direct-zip"> 
    <!-- Have not found a way to exclude b.txt from out.zip --> 
    <delete file="out.zip"/> 
    <zip destfile="out.zip"> 
     <zipgroupfileset dir="." includes="*.zip" /> 
    </zip> 
</target> 

使用unzip-then-rezip,我丢失了a.txtA.txt,因为底层文件系统不区分大小写,并且不能存储这两个文件。使用direct-zip似乎是一个正确的路要走,但我还没有找到一种方法来过滤掉我不希望包含的文件。

即将创建自己的ANT任务来完成这项工作,但我更愿意使用标准ANT任务(甚至是ant-contrib),即使存在性能或可读性惩罚。

回答

0

看一看Ant的Resource Collections,特别是之类的东西restrict,让您在相当灵活的方式筛选文件(ZIP文件内容等)。

这个片段似乎你想要的东西(我的机器上至少 - OSX):

<project default="combine"> 
    <target name="combine"> 
    <delete file="expected.zip" /> 

    <zip destfile="expected.zip"> 
     <restrict> 
     <zipfileset src="src.zip" /> 
     <not> 
      <name name="b.txt" /> 
     </not> 
     </restrict> 
    </zip> 

    </target> 
</project> 

输入文件:

$ unzip -l src.zip 
Archive: src.zip 
    Length  Date Time Name 
-------- ---- ---- ---- 
     0 09-24-11 00:55 a.txt 
     0 09-24-11 00:55 A.txt 
     0 09-24-11 00:55 b.txt 
--------     ------- 
     0     3 files 

输出文件:

$ unzip -l expected.zip 
Archive: expected.zip 
    Length  Date Time Name 
-------- ---- ---- ---- 
     0 09-24-11 00:55 A.txt 
     0 09-24-11 00:55 a.txt 
--------     ------- 
     0     2 files 
+0

虽然这个答案在技术上是正确的,但是当压缩文件非常大时(按条目数)它表现不佳。我没有充分调试脚本以找到根本原因,所以我仍然愿意接受任何人的想法。同时,我创建了一个自定义的ant任务,请参见下文。 – Drew

+0

@drew您使用的是哪种版本的蚂蚁? – matt

+0

Apache Ant(TM)版本1.8.2于2011年6月3日编译。MacOS 10.6.8。为了给一些规模,最后的zip是~12,000个文件和15MByte。 – Drew

1

我最终创建了一个自定义ANT任务来解决问题。该任务接受嵌套的excludes元素,这些元素提供与源zip文件中的entires匹配的正则表达式。

作为额外的好处,我还解决了另一个问题:使用嵌套的rename元素使用正则表达式重命名zip条目。

的ANT代码看起来是这样的:

<filter-zip srcfile="tmp.zip" tgtfile="target.zip"> 
     <exclude pattern="^b\..*$"/> 
     <rename pattern="^HELLO/(.*)" replacement="hello/$1"/> 
    </filter-zip> 

Ant任务的核心看起来是这样的:

zIn = new ZipInputStream(new FileInputStream(srcFile)); 
    zOut = new ZipOutputStream(new FileOutputStream(tgtFile)); 

    ZipEntry entry = null; 
    while ((entry = zIn.getNextEntry()) != null) { 

     for (Rename renameClause : renameClauses) { 
      ... 
     } 
     for (Exclude excludeClause : excludeClauses) { 
      ... 
     } 

     zOut.putNextEntry(...); 
     // Copy zIn to zOut 
     zOut.closeEntry(); 
     zIn.closeEntry(); 
    } 

在我原来的问题,我说我想几个拉链结合一起文件。这在原始问题中使用'direct-zip'方法非常简单。我使用它来创建一个中间的zip文件(tmp.zip),然后我作为源使用我filter-zip任务:

<zip destfile="tmp.zip"> 
     <zipgroupfileset dir="." includes="*.zip" /> 
    </zip> 

此刻我filter-zip任务运行慢一点,则zip(组装所有的拉链)任务......所以表现(可能)非常接近理想。将两个步骤结合在一起将是一个很好的小练习,但对我来说投资回报率并不是很高。