将ANT中的zip存档与过滤和区分大小写相结合

时间:2011-09-23 17:14:10

标签: ant zip

我想使用ANT将几个zip文件组合在一起,但我有三个限制导致标准技术失败:

  1. 有些文件(包含已知的文件名)我不想包含在最终档案中。
  2. 某些源存档包含具有相同名称但大小写不同的文件。
  3. 运行脚本的计算机使用不区分大小写的文件系统。
  4. 为了使我的问题具体,这是一个示例源存档。我知道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),即使存在性能或可读性惩罚。

2 个答案:

答案 0 :(得分: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();
    }

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

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

目前我的filter-zip任务运行速度慢于zip(组装所有拉链)任务...所以性能(可能)非常接近理想状态。将这两个步骤结合在一起将是一个很好的小练习,但对我来说投资回报率不是很高。

答案 1 :(得分: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
相关问题