In the previous parts of this series, we looked at how to make, read, and extract zip archive files using ColdFusion 8's new CFZip and CFZipParam tags. Now, let's finish this up taking a quick look at how we can delete entries within a zip archive. I'm not talking about deleting the actual Zip file - that would best be done using CFFile - I'm talking about deleting items within the archive file. Since this is, by far, the least interesting of all the actions, I am gonna try to keep this brief.
As always, before we can start exploring the deleting of an archive in ColdFusion 8, we have to create a zip archive to work with. We are going to zip the following directory structure:
To create the zip, we are going to use the simple ColdFusion 8 CFZip tag:
<!--- Create a zip archive of the data directory. By default, ColdFusion 8 will recurse the source directory, store the storage paths, and do to our use of Overwrite attribute, we will make sure we create a new zip archive. ---> <cfzip action="zip" source="#ExpandPath( './data/' )#" file="#ExpandPath( './data.zip' )#" overwrite="true" />
This will put all contents of the data directory into the root of our zip archive (the documents and images directory). Now that have a zip archive, the easiest thing we can do is delete everything inside of it using the delete action:
<!--- Delete all contents of the Zip archive. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#" />
Ok, maybe not. This action actually throws the following ColdFusion error:
Cannot delete all the entries from a zip file. There should be at least one entry remaining in the zip file.
When deleting zip archive entries in ColdFusion 8, you have to be careful to leave at least one entry. This also helps us to draw the conclusion that ColdFusion 8 does not allow you have empty directory entries in the archive (despite the fact that listing archive entries can have a type of Directory). In order to avoid this, we can modify the delete action to make sure we only delete certain files. The least destructive thing we can do is to delete a single file using the EntryPath attribute:
<!--- Delete the readme.txt file. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#" entrypath="documents/readme.txt" />
Here, we are deleting the readme.txt file located within the documents folder. As with zip archive extracting, the EntryPath attribute cannot start with the "./" or "/" path constructs. Again, ColdFusion 8 will not thrown any error, it simply won't see the file you are referring to.
To make the action slightly more destructive, we can delete an entire folder by using an EntryPath that references a directory entry:
<!--- Delete the documents directory. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#" entrypath="documents" />
Here, we are deleting the entire documents folder. And again, this EntryPath must not start or end with any "/" path constructs or ColdFusion will simply not find the entry you are referring to.
When we start to delete multiple files at once, as we just did above, we can use the Filter attribute to selectively include files in our zip modification. As we have discussed many times before, the Filter file mask can use the wild card * as well as take a comma delimited list of file masks. In this next example, we will delete entries in the documents folder, but only those that are manuals:
<!--- Delete any manual files that are located within the documents directory. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#" entrypath="documents" filter="manual*" />
This will delete the manual.txt but it will leave the readme.txt file in place.
By default, all delete actions on the zip archive are recursive. That means that if a directory has subdirectories, ColdFusion 8 will delete all files and folders in the target entrypath directory. Therefore, if we simply remove the EntryPath from the example above:
<!--- Delete any manual files that are located anywhere within the zip archive. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#" filter="manual*" />
... we will end up with the same exact result (deleting the manual.txt file in the documents folder). This is because removing the EntryPath will point the delete action at the root of the archive. Then, since ColdFusion 8 zip actions are recursive by default, it will eventually recurse through the subfolders (documents and images) and find the manual.txt file to delete.
To turn off recursive delete, simply set the Recurse attribute to False. This will ensure that only the FILES within the target directory will be deleted and that the subdirectories will not be touched.
As with all CFZip actions, deleting can also be done by using the CFZip tag in conjunction with nested CFZipParam tags. EntryPath, Filter, and Recurse can all be moved into one or more CFZipParam tags. Remember that each CFZipParam tag represents an action; therefore, the Filter attribute of one CFZipParam tag applies only to itself and to no other sibling tags. The same is true for Recurse and EntryPath. To mimic the manual.txt deletion above, we can move the appropriate attributes down into a child tag:
<!--- Delete any manual files that are located anywhere within the zip archive. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#"> <!--- Delete manual files. ---> <cfzipparam filter="manual*" /> </cfzip>
And of course, we can have more than one CFZipParam tag. In this next example, we will delete the manual files and the entire images directory:
<!--- Delete any manual files that are located anywhere within the zip archive. Also delete the entire images directory. ---> <cfzip action="delete" file="#ExpandPath( './data.zip' )#"> <!--- Delete manual files. ---> <cfzipparam filter="manual*" /> <!--- Delete the images directory. ---> <cfzipparam entrypath="images" /> </cfzip>
This will leave us with a zip archive that has just one entry:
So there you have it. Sorry if this part of the series was a bit brief, but I think we have beaten ColdFusion 8's new CFZip tag into the ground. On top of that, I think deleting zip entries is going to be used the least of all the actions.
Want to use code from this post? Check out the license.