A reader (nicely) asked me something before I left for Boston, and I never got around to answering. He had an interesting problem. He wanted to list directories and files, in a recursive fashion, using HTML's unordered list display to handle the directories and their children.
Now I thought this was a simple thing - just use the recurse=true option in <cfdirectory>. However - the more I thought about it - the more difficult it seemed. You can sort the <cfdirectory> result - but not in an way you can simply output with HTML.
My first thought was to switch back to a recursive <cfdirectory>, and while that would work, I assumed I'd lose a lot in terms of speed due to all the file operations. So what I came up with was a mix of recursive CFML and the built-in recursive <cfdirectory> tag:
<cfset initialDir = "c:\apache2\htdocs\testingzone\blogcfc_flex2">
<cfdirectory directory="#initialDir#" recurse="yes" name="files" sort="directory asc">
<cfset display(files,initialDir)>
<cffunction name="display" returnType="void" output="true">
<cfargument name="files" type="query" required="true">
<cfargument name="parent" type="string" required="true">
<cfset var justMyKids = "">
<cfquery name="justMyKids" dbtype="query">
select *
from arguments.files
where directory = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.parent#">
</cfquery>
<cfoutput><ul></cfoutput>
<cfoutput query="justMyKids">
<li>#directory##name#</li>
<cfif type is "Dir">
#display(arguments.files, directory & "" & name)#
</cfif>
</cfoutput>
<cfoutput></ul></cfoutput>
</cffunction>
As you can see, I do the initial <cfdirectory> and have it fetch all the files. The UDF simply handles displaying items from the query. I don't normally do output from UDFs, so to be honest, I feel a bit dirty. I'd probably just wrap it up in a cfsavecontent and return that, but this was written in about 5 minutes. Another problem - note I hard code \ as my file delimiter. I could have made this more dynamic by using a Java call:
<cfset separator = createObject("java","java.io.File").separator>
In general, the use of "/" will work just fine in any OS, however, since I was doing a string comparison in my query, I'd probably want to use the same separator CF used.