tags:

views:

37

answers:

2

Let's say I have a collection of PDF files with the following paths:

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

What I'd like to do is generate thumbnails for each PDF that respect the relative path structure, and output to another location, i.e.:

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

I'd like this to be done in Ant. Assume I'm going to use Ghostscript on the command line and I've already worked out the call to 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>

So what I need to do is work out the correct values for ${thumbnail.image.path} and ${input.pdf.path} while traversing the PDF input directory.

I have access to ant-contrib (just installed the "latest", which is 1.0b3) and I'm using Ant 1.8.0. I think I can make something work using the <for> task, <fileset>s and <mapper>s, but I am having trouble putting it all together.

I tried something like:

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

But unfortunately the @{file} property is an absolute path, and I can't find any simple way of decomposing it into the relative components.

If I can only do this using a custom task, I guess I could write one, but I'm hoping I can just plug together existing components.

+1  A: 

In the sequential task you could may be able to use the ant-contrib propertyregex task to map the input paths to output. For example:

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

Which maps, for example /some/path/pdfs/birds/duck.pdf to /another/path/birds/duck.png.

martin clayton
That looks very interesting. Can you expand your code just a little to show how I'd use that ask? i.e. do I use it in conjunction with the <for> task, and if so, does it go in the <path>?
Shaggy Frog
A: 

For the sake of completeness, here's what I came up with for a target based on martin clayton's answer. It only works on Windows for now but that's because I haven't gotten around to installing Ghostscript in a non-proxy way yet on Mac OS X. Note that to be a cross-platform solution I had to "scrub" the file separators to be consistently forward-slash only.

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