3

I need to get a list of file names in a ZIP file using Apache Ant task without unzipping it first. It also should be OS independent, e.g.: if My.zip contains:

dir1/path/to/file1.html
dir1/path/to/file2.jpg
dir1/another/path/file3.txt
dir2/some/path/to/file4.png
dir2/file5.doc

The Ant task should return the list above with the relative path + filename.

Malvon
  • 1,591
  • 3
  • 19
  • 42

2 Answers2

2

A solution using zipfileset and pathconvert, wrapped in macrodef for reuse :

<project>

<macrodef name="listzipcontents">
 <attribute name="file"/>
 <attribute name="outputproperty"/>

 <sequential>
  <zipfileset src="@{file}" id="content"/>
  <pathconvert property="@{outputproperty}" pathsep="${line.separator}">
   <zipfileset refid="content"/>
   <map from="@{file}:" to=""/>
  </pathconvert>
 </sequential>
</macrodef>

  <listzipcontents file="path/to/whatever.zip|war|jar|ear" outputproperty="foobar"/>

  <echo>$${foobar} => ${foobar}</echo>

</project>

Advantage : you may use all fileset attributes, f.e. include/exclude if you need to filter zipfilecontents - simply expand macrodef with additional attributes for that, also zipfileset supports other archives like jar, war, ear.

Rebse
  • 10,307
  • 2
  • 38
  • 66
  • This is a better overall approach. However, later on, I realized that I needed to extract more information from the zip file contents, i.e. last date of modification/timestamp, size, checksum, etc., and I felt the scripting allows for ease of refinement. Nonetheless, I would like to accept your answer for my original question. – Malvon Jun 01 '16 at 16:46
  • @Malvon for modification/timestamp/size you may take Ant addon Flaka and use it with zipfileset similiar to the last snippet of my answer here => http://stackoverflow.com/a/21891513, also ant has a checksum task => https://ant.apache.org/manual/Tasks/checksum.html; when using Ant Flaka take the last version here => https://github.com/greg2001/ant-flaka; – Rebse Jun 01 '16 at 19:41
  • @Malvon P.S. another Flaka example here => http://stackoverflow.com/a/5992436/130683, otherwise with script it get's more complex, see here => http://stackoverflow.com/a/14740667/130683 – Rebse Jun 01 '16 at 19:48
0

Here's a somewhat cruel way of doing it through script with javascript language in Ant:

<scriptdef name="getfilenamesfromzipfile" language="javascript"> 
    <attribute name="zipfile" /> 
    <attribute name="property" />
    <![CDATA[

          importClass(java.util.zip.ZipInputStream);
          importClass(java.io.FileInputStream);
          importClass(java.util.zip.ZipEntry);
          importClass(java.lang.System);

          file_name = attributes.get("zipfile");
          property_to_set = attributes.get("property");

          var stream = new ZipInputStream(new FileInputStream(file_name));

            try {
              var entry;
                var list;
                while ((entry = stream.getNextEntry()) != null) {
                   if (!entry.isDirectory()) {
                     list = list + entry.toString() + "\n";
                   }
              }

              project.setNewProperty(property_to_set, list);

            } finally {
                stream.close();
            }

    ]]> 

</scriptdef>

Which then can be called in a <target>:

<target name="testzipfile">

  <getfilenamesfromzipfile
      zipfile="My.zip"
      property="file.names.from.zip.file" />

  <echo>List of files: ${file.name.from.zip.file}.</echo>

</target>

Any better solution is welcome.

Malvon
  • 1,591
  • 3
  • 19
  • 42