Search code examples
ant

Copying only files which have another file as a sibling [based on extension]?


I am trying to use ANT to copy some files of a C++ build into another directory.

The output of the build looks like this:

/Build
   /LibA
      LibA.lib
      LibA.pdb
   /LibB
      LibB.lib
      LibB.pdb
   /ProjA
      myexe.exe
      myexe.pdb
   /Foo
      foo.exe
      foo.pdb
   /...

Now, I would like to copy all *.exe files and their *.pdb files to another directory (but not the *.pdb files of the libs).

I tried with:

<copy todir="outdir">
   <fileset dir="Build">
      <include name="**/*.exe" />
      <include name="**/*.pdb" />
   </fileset>
</copy>

However, then I will also get the *.pdb files inside the LibA, LibB, ... folders.

Is there any way I can only copy the pdb-files which have an *.exe-file in the same directory as their sibling?
Unfortunately, the folders are not named in any way that would allow using wildcards based on the folder name.

Of course, I could list each file individually, such as:

<include name="ProjA/*.pdb" />
<include name="Foo/*.pdb" />
<!-- ... -->

However, I am thinking that maybe there is an elegant way where I can specify "copy all *.exe files and all *.pdb files which have an *.exe file next to them".


Solution

  • You could use the <present> selector to find the "sibling" files, something like this:

    <copy todir="outdir">
      <fileset dir="Build" includes="**/*.pdb">
        <present targetdir="Build">
          <mapper type="glob" from="*.pdb" to="*.exe" />
        </present>
      </fileset>
      <fileset dir="Build" includes="**/*.exe" />
      <flattenmapper />
    </copy>
    

    This will only copy the .pdb files with matching .exe files.

    To keep it simple, use a separate fileset for the exe files.

    The flatten mapper is only needed if you want to copy just the files ignoring the directory structure in the source.