Ant解压任务并仅根据另一个目录提取文件

4

我有一个zip文件和一个包含一些文件的目录。我想从zip文件中仅提取在目录中存在的文件(在提取文件时进行文件名转换...基本上,我正在备份这些文件)。

使用带有文件集合和“present”元素的“copy”可以类似地完成类似操作,但是使用unzip似乎无法实现:

<unzip src="${cur.srcdir.live}" dest="${cur.srcdir.archive-files.dir}" overwrite="true">
    <fileset dir=".">
        <present present="both" targetdir="${cur.srcdir}" />
        <type type="file" />
    </fileset>
    <globmapper from="*" to="*.${backup.suffix}" />
</unzip>

有人之前做过这样的事情吗?这是Ant 1.8.0版本。谢谢!


似乎解压任务不支持您发布的表达式。也许您应该将存档解压缩到临时文件夹,然后以刷新模式(借助现有条件)将文件复制到目标文件夹中。 - Alex K
感谢您的建议。作为最后的办法,我会完全解压缩归档文件,但由于有时这些归档文件很大(而且为了一般的优雅),我希望避免这种情况。 - FanOfTamago
我明白了。我已经收藏了你的问题。也许你应该使用带有-f选项(刷新现有文件)的unzip命令?我的意思是,你可以使用exec任务:http://ant.apache.org/manual/Tasks/exec.html - Alex K
3个回答

2

我可以通过“伪造”<present>选择器来解决我的问题,该选择器可用于<copy>。以下是操作步骤:

首先使用 pathconvert 创建文件夹中文件列表:

    <pathconvert property="extract.list" pathsep="&#xA;">
        <path>
            <fileset dir="${extract.src.dir}" includes="${extract.src.dir.relpath}">
                <type type="file" />
            </fileset>
        </path>
        <map from="${extract.src.dir}\" to="" />
    </pathconvert>

注意将地图用户的列表设置为相对路径而不是绝对路径。此外,分隔符是换行符。
然后,该列表被写入文件中:
    <echo file="${props.tmp.file}" message="~~~~noop~~~~&#xA;${extract.list}" append="false" />

我在这里添加了一个“nooop”条目,以确保文件至少有一行。这很重要,因为我们接下来要将其用作包含文件。如果包含文件为空,则Ant会解释为空白表示“允许任何内容”...但我们希望确保空列表不会从zip文件中提取任何内容。
最后一步是使用上面的临时文件作为包含文件从zip文件中提取内容。globmapper在提取时重命名文件,以适当的备份名称进行重命名。
    <unzip src="${extract.archive}" dest="${extract.dest.dir}" overwrite="true">
        <patternset>
            <includesfile name="${props.tmp.file}" />
        </patternset>
        <globmapper from="*" to="*.${backup.suffix}" />
    </unzip>

2

如果有人需要更改目录结构以进行解压缩,请将此添加在此处。我花了很多时间来使它工作。Ant Unzip任务接受cutdirsmapper

<unzip dest="${build.dir}/packages">
    <fileset dir="${src.dir}/packages" includes="*.pkg" />
    <!-- Exctract build folder contents also moving one level up. -->       
    <cutdirsmapper dirs="1" />
    <patternset>
        <include name="build/" />
    </patternset>
</unzip>

我认为这是更好的解决方案。它有效!但是你可以解释一下“dirs”属性,指定从结果中删除多少个嵌套目录。 - Pavoletto

1

您可以尝试通过exec任务调用解压缩命令。
我在Windows上检查的示例只刷新dest.folder中更改的文件:

<property name="zip.file_name" value="Archive.zip"/>
<property name="src.folder" value="d:\"/>
<property name="dest.folder" value="d:\55"/>

<target name="unzip">
    <echo>unzip -fo ${src.folder}${zip.file_name}</echo>
    <exec dir="${dest.folder}" executable="cmd.exe" output="${src.folder}operation_result.txt">

        <arg line="/c unzip -fo ${src.folder}${zip.file_name}"/>
    </exec>
</target>

如果您想保留原始文件,可以使用以下命令:
<arg line="/c unzip -foB ${src.folder}${zip.file_name}"/>

如果使用-B参数,您的原始文件(存储在文件夹中)将被重命名 - 波浪号符号将被添加。您将获得两组文件 - 从归档中提取的文件和旧的原始文件。
之后,您可以通过{{link1:move}}任务来重命名文件。


问题是我不想刷新现有文件。我想提取匹配的文件以备份为目的。假设zip文件包含A、B和C。现在假设我的源目录(在zip之外)包含A和C。我想从zip文件中提取A和C到文件A.backup和C.backup中。你可以从我的问题中看出我有globmapper来实现这个目的,这种技术通常在文件集中非常有效。如果您知道使用exec和解压缩过程来完成此操作的方法,请告诉我! - FanOfTamago
谢谢;我明白你的意思,但我采取了另一种方法来避免使用exec。请查看其他答案。虽然如此,我很感激你和我一起进行头脑风暴! - FanOfTamago

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接