Home | Blog | Twitter @AndyJ | Contact Me | Snippets/Downloads | RSS

Ant: Copying files and directories

I know that I've done a post on copying files with Ant, but I really want to take this further and into more detail. To save my fingers a lot of the text below is taken from my first post as moving and copying directories/files is a similar command in principle.

I also want to mention that I am running all my Ant tasks via Eclipse and not the command line. If there is a demand to know how to install Ant and run it from the command line I'll do that post separately. At this point I'm assuming you've got Eclipse and you know you way around it enough? Before we do begin you will need to ensure that you can see the Console 'View', you can get to this by going to:

   view plainprintabout
 Window >> Show View >> Other >> General >> Console

Before we jump in, if you are on Unix then know that the file permissions are not retained when files are copied; they end up with the default UMASK permissions instead. This is down to the current Java runtimes and the inability to set the permissions. You can get around this by using ANT to call Copy Path view the terminal i.e. instead. If you are on Windows and you copy a file to a directory where that file already exists, but with different casing, the copied file takes on the case of the original. The workaround is to delete the file in the destination directory before you copy it.

Lets begin!

Create a new project in your Eclipse workspace. The type of project doesn't matter, though I'm creating a CFEclipse one as I want to cpoy .cfm pages. From within the project create a new file called Build.xml. Create two more folders in your Ant project called 'folder_test' and 'folder_live' and in the first folder put a file called 'index.cfm'. Your project should now look like this

  • build.xml
    • [folder_live]
    • [folder_test]
      • index.cfm
The idea of the next task to copy index.cfm from the test folder to the live one, i'm also going to introduce properties, think of them as variables.
   view plainprintabout
 <?xml version="1.0" encoding="UTF-8"?>
 <project name="myFirstBuildFile" default="" basedir=".">
     <description>
         A description of what this build file does
     </description>    
     <!-- Relative lo    cation of test folder -->
     <property name="test" value="folder_test/" />
     <!-- Relative location of live folder -->
     <property name="live" value="folder_live/" />
10  
11      <!-- copy file -->
12      <copy file="${test}index.cfm" todir="${live}" />    
13      <echo message="The index.cfm file has been copyd" />
14  </project>
Now while still in the editor right-click anywhere on your build.xml file and choose the following:
   view plainprintabout
 Run As >> Ant Build
If all has gone well you should of just copied your index.cfm file from test to live. Thats all good and well but I doubt you ever have to copy just one file my guess is that you have a host of folders and files. In the directory 'folder_test' add two other directories called 'images' and 'css' and copy 'index.cfm' back as well. You new directory structure should look like this: (feel free to stick some more files into the newly created folders)
  • build.xml
    • [folder_live]
    • [folder_test]
      • [css]
      • [images]
      • index.cfm

The plan now is copy the complete directory of 'folder_test' to 'folder_live':

   view plainprintabout
 <?xml version="1.0" encoding="UTF-8"?>
 <project name="myFirstBuildFile" default="" basedir=".">
     <description>
         A description of what this build file does
     </description>    
     <!-- Relative lo    cation of test folder -->
     <property name="test" value="folder_test/" />
     <!-- Relative location of live folder -->
     <property name="live" value="folder_live/" />
10  
11      <!--
12          copy directories and files
13  
14          From Ant 1.6.3 you can write the following as:
15          <copy file="${test}" tofile="${live}" />
16      -->

17      <copy todir="${live}">
18          <fileset dir="${test}"/>
19      </copy>            
20  
21      <echo message="The contest of folder_test have been copyd" />
22  </project>
Again while in the editor right-click anywhere on your build.xml file and choose the following:
   view plainprintabout
 Run As >> Ant Build

Of course there is more you can do, rather than going through full set examples here or some of the other features:

Copy a set of files to a directory

   view plainprintabout
 <copy todir="${live}">
     <fileset dir="${test}">
         <exclude name="**/*.cfm"/>
     </fileset>
 </copy>
 
 <copy todir="${live}">
     <fileset dir="${test}" excludes="**/
*.cfm"
/>

 </copy>

Copy a set of files to a directory, appending .bak to the file name on the fly

   view plainprintabout
 <copy todir="${live}">
     <fileset dir="${test}"/>
     <globmapper from="*" to="*.bak"/>
 </copy>

Copy a set of files to a directory, replacing @TITLE@ with Foo Bar in all files.

   view plainprintabout
 <copy todir="${live}">
     <fileset dir="${test}"/>
         <filterset>
         <filter token="TITLE" value="Foo Bar"/>
     </filterset>
 </copy>

Collect all items from the current CLASSPATH setting into a destination directory, flattening the directory structure.

   view plainprintabout
 <copy todir="${live}" flatten="true">
     <path>
         <pathelement path="${test}"/>
     </path>
 </copy>

Copies some resources to a given directory.

   view plainprintabout
 <copy todir="${live}" flatten="true">
     <resources>
         <file file="${test}/index.cfm"/>
         <url url="http://www.andyjarrett.co.uk/andy/blog/index.cfm"/>
     </resources>
 </copy>

Copies the two newest resources into a destination directory.

   view plainprintabout
 <copy todir="${live}" flatten="true">
     <first count="2">
         <sort>
             <date xmlns="antlib:org.apache.tools.ant.types.resources.comparators"/>
             <resources>
                 <file file="${test}/file1.txt"/>
                 <file file="${test}/file2.txt"/>
                 <file file="${test}/file3.txt"/>
                 <url url="http://ant.apache.org/index.html"/>
10              </resources>
11          </sort>
12      </first>
13  </copy>

More resources:

Related Blog Entries

TweetBacks
Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Pat Branley's Gravatar Hi Andy
Nice post!
Here is a usefully ANT script i use to just upload files ive worked on since starting my latest update...

[fileset dir="${basedir}" id="changedFiles" ]
[and]
[date datetime="6/25/2007 9:00 AM" when="after" /]                    
[/and]
[/fileset]

I then wrap that in a FTP task when i need those files to go to a remote server rather than a file i have mapped.

Pat
# Posted By Pat Branley | 6/25/07 12:44 AM
Andy J's Gravatar Cheers Pat, I'm gonna cover FTP in another post soon :o)
# Posted By Andy J | 6/25/07 7:53 AM
Jim Priest's Gravatar Great stuff! I love Ant! Hope you don't mind but I've added your Ant related posts to my wiki:

http://www.thecrumb.com/wiki/Ant
# Posted By Jim Priest | 6/25/07 1:01 PM
Alex Egg's Gravatar Hi,

I'm trying sort my input to the concat task alphabeticly with this:

   <concat destfile="${temp}/s3/management.css">
   <sort>
         <!--this sort does not work if there are over 9 files -->
         <name xmlns="antlib:org.apache.tools.ant.types.resources.comparators"/>
            <fileset dir="${temp}/assets/min/css/" includes="*.css"/>
      </sort>
</concat>

My files are named 1styles.css, 2styles.css, 3styles.css, etc. However, once the count reaches 10 the order gets messed up and 10styles.css is loaded first.

How can I load them by the numbers 1-10 ?
# Posted By Alex Egg | 7/24/07 3:14 AM
BlogCFC / created by Raymond Camden / running version 5.9.5.003 / Contact AndyJarrett.com / Pet Rescue SOS