Ask a Jedi: Dumping a Recursive Directory List

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 = ““>

&lt;cfquery name="justMyKids" dbtype="query"&gt;
select	*
from	arguments.files
where	directory = &lt;cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.parent#"&gt;
&lt;/cfquery&gt;	

&lt;cfoutput&gt;&lt;ul&gt;&lt;/cfoutput&gt;

&lt;cfoutput query="justMyKids"&gt;
	&lt;li&gt;#directory#\#name#&lt;/li&gt;
	&lt;cfif type is "Dir"&gt;
		#display(arguments.files, directory & "\" & name)#
	&lt;/cfif&gt;
&lt;/cfoutput&gt;

&lt;cfoutput&gt;&lt;/ul&gt;&lt;/cfoutput&gt;

</cffunction> </code>

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.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Comments