Copying Files Using Phing

6th January 2009 - 4 minutes read time

One of the main reasons to use Phing is to create a copy of your project in another directory that you can then use as your distribution copy. Your working directory might contain lots of testing code that is not needed in the final build.

To copy a file from one directory to another using Phing you need to use the copy element. Here is a simple example where a single file is copied from one directory to another.

<?xml version="1.0"?>
<!-- build xml -->
<project name="myProject" default="main">
 <target name="main">
     <copy file="index.php" tofile="myProject_build/index.php" />
 </target>
</project>

This isn't entirely useful as you will need to create a rule for every file you want transferred, which might be a few. To copy a directory you need to set up a fileset element. This will contain a list of files and directories that you want to be copied. A fileset element can contain include and exclude rules that govern which files will be used. Here is an example of a fileset, which would normally be on the root of the project element.

<fileset dir="./" id="myProjectFiles">
 <exclude name="**/*_test.php" />
 <include name="**/*.php" />
</fileset>

In this example we are excluding any file in this and any sub directory that has a filename ending in _test.php as these will be our test files that we don't want copied. We then include any file that contains the .php extension. Because any exclude rules override any include rules this will work as expected and only copy across .php files without a _test at the end of the file name.

You can also specify a directory and everything in it by using the following include rule.

<include name="something/**" />

The previous fileset example can also be written as the following, although I don't recommend this as it can get complicated!

<fileset dir="./" id="myProjectFiles" includes="**/*.php something/**" excludes="**/*_test.php" />

To do something useful with this fileset we can use the copy element again. The main difference here is that we are using the todir attribute of the copy element to designate the destination of the copy.

<?xml version="1.0"?>
<!-- build xml -->
<project name="myProject" default="main">
 
 <fileset dir="./" id="myProjectFiles">
  <exclude name="**/*_test.php" />
  <include name="**/*.php" />
 </fileset>
 
 <target name="main">
  <copy todir="./myProject_build">
   <fileset refid="myProjectFiles" />
  </copy>
 </target>
</project>

If you run this it will copy all the files (without the exceptions) and directories from the current directory to a directory called myProject_build. If the destination directory doesn't exist then phing will create it. This works well, but if you run this code a second time it will copy the myProject_build into itself and you will get a recursive directory structure, which is quite messy and probably not what you want. There are two ways to prevent this. The first is to store your project in a subdirectory from your build.xml file and change your fileset rule accordingly. The second way is to add on an exclude rule to your fileset to specifically ignore the build directory and all of its contents.

<exclude name="myProject_build/**" />

Using the fileset and copy elements in this manner allows you to perform operations on the files as you copy them. This might be, for example, adding in a version number to the top of each file using a token replace.

Automated Build With Phing

Add new comment

The content of this field is kept private and will not be shown publicly.