Ant Zip Extracted Parent Directory - ant

I have several zip files that I need to unzip within an Ant target. All the zip files are in the same directory, and have the same internal directory and file structure.
So I am using the following snippet to unzip all the zip files in the directory, but each zip file does not contain a parent folder at the root, so each successive zip file is unzipped and overwrites the previous files.
<unzip dest="C:/Program Files/Samsung/Samsung TV Apps SDK/Apps">
<fileset dir=".">
<include name="**/*.zip"/>
</fileset>
</unzip>
Is there a better way to unzip a group of files, and create a directory to unzip them to that is based on the zip file name?
So, if the zip files are:
1.zip
2.zip
3.zip
then the content of each will be extracted to:
1/
2/
3/
Thanks

One solution might be to use the ant-contrib 'for' and 'propertyregex' tasks to do this:
<for param="my.zip">
<fileset dir="." includes="**/*.zip" />
<sequential>
<propertyregex property="my.zip.dir"
input="#{my.zip}"
regexp="(.*)\..*"
select="\1"
override="yes" />
<unzip src="#{my.zip}" dest="${my.zip.dir}" />
</sequential>
</for>
The 'propertyregex' strips the .zip extension from the zip file name to use as the target directory name.

Without ant-contrib:
https://stackoverflow.com/a/12169523/957081
<!-- Get the path of the war file. I know the file name pattern in this case -->
<path id="warFilePath">
<fileset dir="./tomcat/webapps/">
<include name="myApp-*.war"/>
</fileset>
</path>
<property name="warFile" refid="warFilePath" />
<!-- Get file name without extension -->
<basename property="warFilename" file="${warFile}" suffix=".war" />
<!-- Create directory with the same name as the war file name -->
<mkdir dir="./tomcat/webapps/${warFilename}" />
<!-- unzip war file -->
<unwar dest="./tomcat/webapps/${warFilename}">
<fileset dir="./tomcat/webapps/">
<include name="${warFilename}.war"/>
</fileset>
</unwar>

Related

I wan to unzip multiple files in a folder with the same name as the file name using Ant?

I have a folder with multiple .zip files. I want to unzip them in the same folder, with the name same as that of the file.
eg.
temp/product_file1.zip
temp/product_file2.zip
temp/product_file3.zip
Output expected:
temp/product_file1
temp/product_file2
temp/product_file2
How can I make a generic code using Ant?
The code which I am using now is able to only unzip the last file.
<path id="warFilePath">
<fileset dir="/temp">
<include name="product_*.zip"/>
</fileset>
</path>
<property name="warFile" refid="warFilePath" />
<basename property="warFilename" file="${warFile}" suffix=".zip" />
<unzip dest="temp/${warFilename}">
<fileset dir="/temp">
<include name="${warFilename}.zip"/>
</fileset>
</unzip>

How to compile each jasper file to its own directory?

I'm trying to create a ant script to compile my jasper files, but I have many "srcdir" and "destdir":
<target name="all">
<jrc
srcdir="many..."
destdir="many..."
tempdir="any"
xmlvalidation="true">
<classpath refid="classpath"/>
<include name="**/*.jrxml"/>
</jrc>
</target>
...and I would like it to compile each file to it's own dir. For every ".jrxml" file.
Is there a way?
You can use ant-contrib foreach task to loop over each jrxml file and call the jrc task for each of those. If you don't have it, you'll need to install ant-contrib by copying its JAR file to the lib directory of your Ant installation (if you're using Eclipse, you can add it by going to "Window > Preferences > Ant > Runtime" and adding the JAR into "Ant Home Entries").
The following defines a target "all" that will select all the jrxml files under the current directory. For each of those file, the "jrc" target will be called and the corresponding file will be referenced by the property jrxml.file.
Inside this task, the directory where the jrxml file is located is retrieved with the dirname task and the name of the jrxml file is retrieved with the basename task. The built .jasper file will be created under a folder having the same name as the jrxml file. (It needs to be created first with the mkdir task).
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<target name="all">
<foreach target="jrc" param="jrxml.file">
<path>
<fileset dir=".">
<include name="**/*.jrxml"/>
</fileset>
</path>
</foreach>
</target>
<target name="jrc">
<dirname property="jrxml.dir" file="${jrxml.file}"/>
<basename property="jrxml.filename" file="${jrxml.file}" suffix="jrxml"/>
<mkdir dir="${jrxml.dir}/${jrxml.filename}"/>
<jrc srcdir="${jrxml.dir}"
destdir="${jrxml.dir}/${jrxml.filename}"
tempdir="${jrxml.dir}/${jrxml.filename}"
xmlvalidation="true">
<classpath refid="classpath"/>
<include name="${jrxml.filename}.jrxml"/>
</jrc>
</target>
As an example, if you have a structure:
+folder
+--jrxml
+----Example1.jrxml
+----Example2.jrxml
the result will be
+folder
+--jrxml
+----Example1.jrxml
+----Example1
+------Example1.jasper
+----Example2.jrxml
+----Example2
+------Example2.jasper

ant checksum directory does not reflect removed files

I have the following ant targets defined. The idea is to do the heavy work only, if some contents of a folder have changed.
<target name="checksumAssets">
<echo message="verify checksums" />
<checksum todir="${bin.loc}/../checksums" verifyproperty="checksum.isUpToDate.test">
<fileset dir="${bin.loc}/assets/" id="filelist">
<include name="somefolder/" />
<exclude name="somefolder/result.swf"/>
</fileset>
</checksum>
<echo message="${toString:filelist}"/>
<echoproperties regex="checksum.isUpToDate.test"/>
</target>
<target name="createAsset" depends="checksumAssets" unless="${checksum.isUpToDate.test}">
<!-- do create the assets and other magic -->
<echo message="create checksum files" />
<checksum todir="${bin.loc}/../checksums" >
<fileset refid="filelist" />
</checksum>
</target>
somefolder contains images which will be processed and result in a swf file containing these assets.
i want this heavy processing only to take place if something in the asset folder changes.
this works as espected in two cases:
i add a new file to somefolder
i change an existing file in somefolder
my problem is:
it does not work when i delete a file from this folder.
this means, the createAsset Target is not called on ant createAsset if i remove a file from the folder in question. it is called in the two aforementioned cases and if there are no checksum files present in the checksums folder.
is there something i missed?
ant version is 1.8.2
i've found a workaround.
since <checksum> only saves the checksum of single files, it cannot know if a file is missing from a previous run. for this it would need to save the checksum of a complete filelist on disk.
this is what i accomplished:
<target name="checksumAssets">
<echo message="verify checksums" />
<!-- generate filelist.txt with actual content of somefolder -->
<fileset dir="${bin.loc}/assets/somefolder/" id="filelist">
<exclude name="result.swf"/>
<exclude name="filelist.txt"/>
</fileset>
<concat destfile="${bin.loc}/assets/somefolder/filelist.txt" fixlastline="true">${toString:filelist}</concat>
<!-- checksum folder including the filelist.txt -->
<checksum todir="${bin.loc}/../checksums" verifyproperty="checksum.isUpToDate.test">
<fileset dir="${bin.loc}/assets/" id="checkedlist">
<include name="somefolder/" />
<exclude name="somefolder/result.swf"/>
</fileset>
</checksum>
</target>
<target name="createAsset" depends="checksumAssets" unless="${checksum.isUpToDate.test}">
<!-- do create the assets and other magic -->
<echo message="create checksum files" />
<checksum todir="${bin.loc}/../checksums" >
<fileset refid="checkedlist" />
</checksum>
</target>
first i generate a filelist.txt with the content of the current folder.
then i generate checksums of all files in this folder, including the filelist.txt
on every an run, filelist.txt will be generated and checked against the filelist.txt from the last successful run of createAsset.
now the createAsset target is run if a content file changes or if the content of this folder changes.
mission accomplished ;)

Ant unzip task and only extracting files based on another directory

I have a zip file and, separately, a directory that contains some files. From the zip file I'd like to extract only those files that exist in the directory (performing a filename transformation on the files as they are being extracted..basically, I'm making backups of those files).
There is no problem doing something similar with a <copy> that has a fileset with a <present> element, but it doesn't seem to be working for me with 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>
Has anyone done something like this before? This is Ant 1.8.0. Thanks!
I was able to solve my problem by "faking" the <present> selector that can be used in <copy>. Here's how:
First I used pathconvert to create a list of the files in my folder:
<pathconvert property="extract.list" pathsep="
">
<path>
<fileset dir="${extract.src.dir}" includes="${extract.src.dir.relpath}">
<type type="file" />
</fileset>
</path>
<map from="${extract.src.dir}\" to="" />
</pathconvert>
Notice the user of a map to have the list be relative paths instead of absolute paths. Plus, the delimiter is a newline.
Then this list gets written to a file:
<echo file="${props.tmp.file}" message="~~~~noop~~~~
${extract.list}" append="false" />
I put that "nooop" entry in there so that the file always has at least one line. This is important because of our next step where we use this as an includesfile. If the includesfile is empty, Ant interprets that as "allow anything"...but we want to make sure that an empty list results in nothing getting extracted from the zip.
Last step is to extract from the zip using our temp file from above as an includes file. The globmapper renames the files upon extraction, to the appropriate backup names:
<unzip src="${extract.archive}" dest="${extract.dest.dir}" overwrite="true">
<patternset>
<includesfile name="${props.tmp.file}" />
</patternset>
<globmapper from="*" to="*.${backup.suffix}" />
</unzip>
Adding this here in case someone needs to change the directory structure on extraction. I've spent so much trying to make this working. Ant Unzip task accepts 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>
You can try calling unzip command via exec task.
The sample that I checked on Windows that refresh only changed files in 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>
If you want to stay your original files you can use this command:
<arg line="/c unzip -foB ${src.folder}${zip.file_name}"/>
In case using -B parameter your original files (stored in folder) will be renamed - the tilde symbol will be appended. You get two sets of files - extracted from archive and old original files.
After that you can rename files with the help of move task.

Relocate contents of dynamic folder

I have a zip file which has one base folder inside it with other content inside that. I don't always know what that base folder is going to be called until I unzip it.
I'd like to move that base folder, and rename it at the same time, in ant - but can't seem to find out how. I've written code to extract the contents of the zip file to ${local.sdk.dir}/temp/ but from here i can't work out how to rename/move the extracted folder
<move todir="${local.sdk.dir}/${remote.sdk.file.name}">
<fileset dir="${local.sdk.dir}/temp/<WHAT_DO_I_PUT_HERE?>"></fileset>
</move>
also tried
<move todir="${local.sdk.dir}/${remote.sdk.file.name}" includeEmptyDirs="yes" verbose="true">
<fileset dir="${local.sdk.dir}/temp/" >
<include name="**/*" />
</fileset>
</move>
and played about with this, but closest I can get without ant throwing an error is to copy the contents of the temp dir, not the base folder within temp.
You can do all this in one step - copy from the zip file and rename the files changing the dir name as you copy. The copy task accepts a nested resource collection, so you can use a zipfileset to specify the files to copy directly from the zip file.
In order to rename the files as they are copied, you can use a mapper, which the copy task also takes as a nested element. In this case, a cutsdirmapper looks like the tool for the job.
So, if I've understood what you want to do correctly, something like this should work:
<copy todir="${local.sdk.dir}/${remote.sdk.file.name}">
<zipfileset src="${your.zip.file}" />
<cutdirsmapper dirs="1" />
</copy>
cutdirsmapper is only available in Ant 1.8.2 onward, so if you're using an earlier version, you could try a regexpmapper:
<regexpmapper from="[^/]*(.*)" to="\1" />
Similar to this question
<target name="relocate_sdk_folder">
<path id="sdk_folder_name">
<dirset dir="${local.sdk.dir}/temp/">
<include name="*"/>
</dirset>
</path>
<property name="sdk_folder_name" refid="sdk_folder_name" />
<echo message="renaming ${sdk_folder_name} to ${remote.sdk.file.name}" />
<move file="${sdk_folder_name}" tofile="${local.sdk.dir}/${remote.sdk.file.name}" />
</target>

Resources