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">
<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">
where directory = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.parent#">
<cfif type is "Dir">
#display(arguments.files, directory & "\" & name)#
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.