【问题标题】:Iterating through a directory with Ant使用 Ant 遍历目录
【发布时间】:2010-05-17 22:00:18
【问题描述】:

假设我有一组具有以下路径的 PDF 文件:

/some/path/pdfs/birds/duck.pdf
/some/path/pdfs/birds/goose.pdf
/some/path/pdfs/insects/fly.pdf
/some/path/pdfs/insects/mosquito.pdf

我想做的是为每个 PDF 生成尊重相对路径结构的缩略图,并输出到另一个位置,即:

/another/path/thumbnails/birds/duck.png
/another/path/thumbnails/birds/goose.png
/another/path/thumbnails/insects/fly.png
/another/path/thumbnails/insects/mosquito.png

我希望这可以在 Ant 中完成。假设我将在命令行上使用 Ghostscript,并且我已经完成了对 GS 的调用:

    <exec executable="${ghostscript.executable.name}">
        <arg value="-q"/>
        <arg value="-r72"/>
        <arg value="-sDEVICE=png16m"/>
        <arg value="-sOutputFile=${thumbnail.image.path}"/>
        <arg value="${input.pdf.path}"/>
    </exec>

所以我需要做的是在遍历 PDF 输入目录时计算出 ${thumbnail.image.path}${input.pdf.path} 的正确值。

我可以访问 ant-contrib(刚刚安装了“最新”版本,即 1.0b3)并且我使用的是 Ant 1.8.0。我想我可以使用 &lt;for&gt; 任务、&lt;fileset&gt;s 和 &lt;mapper&gt;s 完成一些工作,但我无法将它们组合在一起。

我尝试了类似的方法:

    <for param="file">
        <path>
            <fileset dir="${some.dir.path}/pdfs">
                <include name="**/*.pdf"/>
            </fileset>
        </path>
        <sequential>
            <echo message="@{file}"/>
        </sequential>
    </for>

但不幸的是,@{file} 属性是绝对路径,我找不到任何简单的方法将其分解为相关组件。

如果我只能使用自定义任务来做到这一点,我想我可以编写一个,但我希望我可以将现有组件组合在一起。

【问题讨论】:

    标签: ant fileset


    【解决方案1】:

    在顺序任务中,您可以使用ant-contrib propertyregex 任务将输入路径映射到输出。例如:

    <propertyregex override="yes" property="outfile" input="@{file}"
                   regexp="/some/path/pdfs/(.*).pdf"
                   replace="/another/path/\1.png" />
    

    哪个映射,例如 /some/path/pdfs/birds/duck.pdf/another/path/birds/duck.png

    【讨论】:

    • 这看起来很有趣。您能否稍微扩展您的代码以显示我将如何使用该问题?即我是否将它与 任务结合使用,如果是,它是否进入
    【解决方案2】:

    为了完整起见,这是我根据马丁·克莱顿的回答提出的目标。它目前仅适用于 Windows,但那是因为我还没有在 Mac OS X 上以非代理方式安装 Ghostscript。请注意,作为跨平台解决方案,我必须“清理”文件分隔符始终只使用正斜杠。

    <target name="make-thumbnails" depends="">
        <taskdef resource="net/sf/antcontrib/antlib.xml">
            <classpath>
                <pathelement location="/path/to/ant-contrib-1.0b3.jar"/>
            </classpath>
        </taskdef>
    
        <condition property="ghostscript.executable.name" value="/path/to/gswin32c.exe">
            <os family="windows"/>
        </condition>
        <condition property="ghostscript.executable.name" value="">
            <os family="mac"/>
        </condition>
    
        <for param="file">
            <path>
                <fileset dir="/path/to/pdfs">
                    <include name="**/*.pdf"/>
                </fileset>
            </path>
            <sequential>
                <propertyregex override="yes" property="file-scrubbed" input="@{file}"
                                    regexp="\\"
                                    replace="/" />
                <propertyregex override="yes" property="output-path-directory-fragment" input="${file-scrubbed}"
                                    regexp=".*/pdfs/(.*)/.+\.pdf"
                                    replace="\1" />
                <propertyregex override="yes" property="output-path-file-fragment" input="${file-scrubbed}"
                                    regexp=".*/pdfs.*/(.+)\.pdf"
                                    replace="\1.png" />
                <mkdir dir="${thumbnails.base.dir}/${output-path-directory-fragment}"/>
                <exec executable="${ghostscript.executable.name}">
                    <arg value="-q"/>
                    <arg value="-dLastPage=1"/>
                    <arg value="-dNOPAUSE"/>
                    <arg value="-dBATCH"/>
                    <arg value="-dSAFER"/>
                    <arg value="-r72"/>
                    <arg value="-sDEVICE=png16m"/>
                    <arg value="-sOutputFile=${thumbnails.base.dir}/${output-path-directory-fragment}/${output-path-file-fragment}"/>
                    <arg value="${file-scrubbed}"/>
                </exec>
            </sequential>
        </for>
    </target>
    

    【讨论】:

    • 你能解释一下最后 2 个propertyregex 是做什么的吗,真的没有得到替代品吗?也许一些输入和预期输出示例会有所帮助
    • 你的属性正则表达式在这里救了我的命......尽管我想指出“覆盖”属性接受“真”或“假”。干杯