Renaming files with dir values using Ant? - ant

I have the following simple thing to do with Ant but did not find how to do that:
move build/xxx/file.ext to dest/xxxfile.ext
I'm no Ant Guru .
file.ext is constant in this particular case
Nota : xxx can take many values so I want to apply to all these values

You need to use a mapper element to generate the destination file names. This is derived from the Ant mapper docs:
<move todir="dest">
<fileset dir="build" includes="*/*.ext" />
<mapper type="regexp" from="^([^/]*)/([^/]*)" to="\1\2"/>
</move>

When in doubt, an exec will do the job for you, but it's not always the best way.
Try the move task.
<move file="build/xxx/file.ext" tofile="dest/xxxfile.ext"/>

Related

Why does ANT update the contents of a fileset after it was created, and can I override this?

I think this may be easiest explained by an example, so here goes:
<target name="test">
<fileset id="fileset" dir="target">
<include name="*"/>
</fileset>
<echo>${toString:fileset}</echo>
<touch file="target/test"/>
<echo>${toString:fileset}</echo>
</target>
Outputs:
test:
[echo]
[touch] Creating target/test
[echo] test
What I ideally want is to have the fileset stay the same so I can have a before/after set (in order to get a changed set using <difference>, so if you know of a way to skip right to that...).
I've tried using <filelist> instead, but I can't get this correctly populated and compared in the <difference> task (they're also hard to debug since I can't seem to output their contents). I also tried using <modified/> to select files in the fileset, but it doesn't seem to work at all and always returns nothing.
Even if there is an alternative approach I would appreciate a better understanding of what ANT is doing in the example above and why.
The path selector is evaluated on the fly. When a file is added, it will reflect in the set when you use it.
You may able to evaluate and keep it in variable using pathconvert. Then this can be converted back to filest using pathtofilest
A fileset is something like a selector. It's a set of "instructions" (inclusions, exclusions, patterns) allowing to get a set of files.
Each time you actually do something with the fileset (like printing the files it "references"), the actual set of files is computed based on the "instructions" contained in the fileset.
As Jayan pointed out it might be worth posting the final outcome as an answer, so here's a simplified version with the key parts:
<fileset id="files" dir="${target.dir}"/>
<pathconvert property="before.files" pathsep=",">
<fileset refid="files"/>
</pathconvert>
<!-- Other Ant code changes the file-system. -->
<pathconvert property="after.files" pathsep=",">
<fileset refid="files"/>
</pathconvert>
<filelist id="before.files" files="${before.files}"/>
<filelist id="after.files" files="${after.files}"/>
<difference id="changed.files">
<filelist refid="before.files"/>
<filelist refid="after.files"/>
</difference>

Run pngquant through an Ant task

I've been attempting unsuccessfully to create a custom Ant task that processes a bunch of PNG files using pngquant.
Here's what I've been trying to so far (and I've been running it as a part of the HTML5 Boilerplate Build Script, so that's where the dynamic values are coming from):
<apply executable="${basedir}/${dir.build.tools}/pngquant" dest="./${dir.publish}/${dir.images}/" osfamily="unix">
<fileset dir="./${dir.source}/${dir.images}/" includes="**/*.png" excludes="${images.bypass}, ${images.default.bypass}"/>
<arg value="-force 256"/>
<targetfile/>
<srcfile/>
<mapper type="identity"/>
</apply>
Currently, each image errors with "cannot open for reading".
I know this may not be very helpful, but I really don't know where to go from here. Any help would be very much appreciated.
I don't know what the problem is, but I think there are something wrong with your Ant XML itself.
First of all, your excludes has a additional space after the comma.
excludes: comma- or space-separated list of patterns of files that must be excluded.
That is to say, you should either use comma, or space, not together. So it should be ${images.bypass},${images.default.bypass}. ---- I found that it is not right. It uses StringTokenizer(String sInput, String sDelimiter, boolean bReturnTokens) and passes false to the third parameter, so that you can use , together.
Also, I recommend you use nested <include> and <exclude> element to make it more clear.
Second, you don't need to put <targetfile/> and <srcfile/> inside <apply> if you don't need to use them.
Third, <arg value="-force 256" /> should be <arg value="-force"/> and <arg value="256"/>.

Ant exclude file based on it's content

Is there any way to exclude files from an ant fileset based on the file content?
We do have test servers where code files are mixed up with files that have been generated by a CMS.
Usually, the files are placed in different folders, but there is a risk that real code files are in the middle of generated code.
The only way to differentiate generated files is to open the files and look at it's content. If the file contains a keyword, it should be excluded.
Does anyone know a way to perform this with Ant?
From the answer provided by Preet Sangha, Ishould use a filterchain. However, I'm missing a step here.
Let's say I load a text file of exclusions to be performed:
<loadfile property="exclusions" srcFile="exclusions.txt" />
But I don't know how to integrate it into my current copy task:
<copy todir="${test.dir}">
<fileset dir="${src.dir}">
</fileset>
</copy>
I tried to add the following exclude to the fileset but it does not do anything:
<exclude name="${exclusions}"/>
I'm sure I'm missing a simple step...
Have a look at the not and contains selectors.
The not selector contains an example of pretty much exactly what you're trying to do.
<copy todir="${test.dir}">
<fileset dir="${src.dir}">
<not>
<contains text="your-keyword-here"/>
</not>
</fileset>
</copy>
There's also the containsregexp selector which might be useful if your criteria for exclusion is more complicated.
There's a load more selectors you can use to refine your selection if needed.
I don't know ant but reading the docs....
Can you build a files list using a filterchain, and put this into the excludefiles of a fileset?
or
perhaps create a fileset with a filterchain that uses a filterreader and linecontainsregexp

Passing optional path arguments to ant

I have an ant task that uses an apply task to run a script on a group of files.
I have a directory structure resultant of something like this:
mkdir -p a/{b,c,d,e}/f
Normally (if I pass no arguments), I would like ant to run on all fs.
That is, if I called ant mytask, it should process: a/b/f, a/c/f, a/d/f, a/e/f. This already works using apply and patternsets.
However, when I pass it an optional argument called foo, it should only call the script on a/foo/f.
So if I called ant mytask -foo b, it should process a/b/f only, and not the others.
I have read this SO post, which explains ways of passing arguments, and I have looked at the ant documentation regarding properties, and conditionals. But I am still unable to piece them together in a way that works.
Also, I do not want to use one of the suggestions from the SO above which called for arguments like this:
<arg value="${arg0}"/>
<arg value="${arg1}"/>
I want to be able to call it as ant mytask -foo valueoffoo for any arbitrary foo.
Thanks.
I tried martin clayton's suggestion below and have code like:
<target name="mytask">
<property name="foo" value="*" />
<apply executable="perl">
<arg value="somescript"/>
<dirset id="them" dir="a">
<include name="${foo}/*/f" />
</dirset>
</apply>
</target>
The above does what I want.
Note 1: In my actual code I use a patternset instead of dirset but it should work the same.
Note 2: In my original question I said the directory structure was a/{b,c,d,e}/f. It is in fact a bit more complicated, hence the * in the include above. I omitted that the first time around because it did not seem relevant.
You can do this - albeit with a slightly different command-line syntax -
using a property 'override'.
First, in the buildfile, construct your fileset or dirset from a property foo,
something like this:
<property name="foo" value="*" />
<dirset id="them" dir="a">
<include name="${foo}/f" />
</dirset>
This will give you your default behaviour - processing all
subdirectories of a that themselves have a subdirectory f.
Now, if you run Ant like this:
ant -Dfoo=d
Only directory a/d/f will be processed.
This works because Ant properties are not mutable - well, not normally anyway -
so the command-line definition of foo prevents the one within the buildfile from being used.

Store a Value in a Property with Ant or Phing

With Ant or Phing, I need to load a file's contents into a property, run a regular expression on the value of that property, and then store the result of that regular expression in another property. What's the best way to do this?
I can load the file into a property easily (with Phing) like so:
<loadfile file="myfile.txt" property="my.file" />
And I know how to update the file, but I can't seem to figure out how to run a regex on that property, and store the result in a new property for future use.
Any help would be greatly appreciated!
Update
I've been tinkering with it, and this will work. Let me know if there's a streamlined way though! The code below loads a file into a property, then reduces it to only the line that contains the title tag. And then, it runs a regular expression on that line, and stores the contents of that tag in my.prop.
<loadfile file="../index.html" property="my.prop">
<filterchain>
<linecontainsregexp>
<regexp pattern="<title>" />
</linecontainsregexp>
<replaceregexp>
<regexp pattern="[\s\S]+<title>(.+?)</title>" replace="$1" />
</replaceregexp>
</filterchain>
</loadfile>
Update 2
Actually, I ended up using an adhoc task to create my own. Worked perfectly!
You can run an arbitrary command from an ant target like this:
<exec executable="bash">
<arg line="script.sh"/>
</exec>
You can for example store the result of the regexp in a tmp file and then load it into another property the same way as the initial one.
In Phing you could process the content of the property where you loaded the file using the "php" task. See: http://www.phing.info/docs/guide/stable/chapters/appendixes/AppendixB-CoreTasks.html#PhpEvalTask

Resources