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.