Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at cf.Objective() 2009 (Minneapolis, MN) with:

CFDirectory Filtering Uses Single Character Wild Card

By Ben Nadel on
Tags: ColdFusion

Minor tip here, but over the weekend, at cf.Objective(), I was watching a presentation (I think it was Mark Mandel) when I saw that someone was using a ColdFusion CFDirectory filter that had the "?" wild card. I knew that CFDirectory filtering could use the multi-character "*" wild card, but I am pretty sure I didn't know that it could use the single-character wild card. Very cool!. How did this escape my attention? I ran a quick test just to make sure I wasn't misunderstanding what was going on. In this demo, I am going to list all files in a directory followed by a list of only the files that have a three character file name:

  • <!--- Get all files. --->
  • <cfdirectory
  • action="list"
  • directory="#ExpandPath( './' )#"
  • listinfo="name"
  • name="qFile"
  • />
  •  
  • <!--- Output file list. --->
  • <cfdump
  • var="#qFile#"
  • label="All Files"
  • />
  •  
  • <br />
  •  
  • <!---
  • Get files that have only THREE characters followed by
  • and extension type.
  • --->
  • <cfdirectory
  • action="list"
  • directory="#ExpandPath( './' )#"
  • listinfo="name"
  • filter="???.*"
  • name="qFile"
  • />
  •  
  • <!--- Output file list. --->
  • <cfdump
  • var="#qFile#"
  • label="File List With Three Characters"
  • />

This gives us the following two CFDump outputs:


 
 
 

 
CFDirectory Of All Files In A Directory  
 
 
 

 
 
 

 
CFDirectory Showing Only Files With Three Letter File Names Due To Single-Character Wild Cards  
 
 
 

Works like a charm. This would definitely have come in handy several times in the past. At least I will know it going forward. I just looked in the ColdFusion 8 documentation to see if this was mentioned and sure enough, it's right there. I guess I have to be better about reading the documentation.




Reader Comments

You really do learn something everyday! I just wish you could use mulitple filters, that would really come in hand. filter="*.png,*.gif,*.jpg"

Reply to this Comment

@Dan,

You can do just that:

<cfdirectory
action="list"
directory="#ExpandPath( './' )#"
name="qFile"
sort="name ASC"
filter="*.pdf|*.zip|*.doc|*.docx|*.ppt|*.pptx|*.pot|*.dot|*.xls|*.xlsx|*.swf|*.rtf" />

Reply to this Comment

I will have to give that a try, great if it works though. I always remember the docs saying only 1 filter can be applied. Thanks!

Reply to this Comment

It works great! This is straight from the docs and probably why I was confused about that > File extension filter applied to returned names, for example, *.cfm. One filter can be applied. Thanks again.

Reply to this Comment

@Dan,

I just tried it an it works! However, I did not see this in the documentation. Does it mentions Pipes anywhere or demonstrate their use?

Reply to this Comment

No mention of pipes anywhere. Is there a secret handshake I need to learn to get the real docs? If so I will practice.

Reply to this Comment

@Dan - There's no secret handshake, I think this is the case of us developers having to poke Adobe to improve/clarify the documentation.

Reply to this Comment

Todd is correct. The pipe symbol is just an OR statement (not sure if it's regex or not).

However, I just tried it once a long time ago when commas weren't doing the trick.

Reply to this Comment

? symbol in regex is 0 or 1. So, when you write: ???.* it should match:

ben.txt
ai.txt
i.txt
.txt <-- possible on a *nix box.

...etc.

Reply to this Comment

Be careful. In the CFZip and CFZipParam tags, which also have filtering, the comma works like the pipe. Same thing, slightly different rules, so not sure if saying that this is a regular expression will work.

Reply to this Comment

@Todd,

The ? does not work like a regular expression question mark. In my example, ????.* ONLY matches "anna.txt". By your logic, it should also match "ben.txt". These are not regular expressions.

Reply to this Comment

@Ben: Could be that my regex-fu is failing or isn't strong enough. On my cheat sheet, it clearly says ? = 0 or 1. Maybe I'm misunderstanding that. I ran ????.* through RegexBuddy and it throws an error saying The quanitifier ? can only be used after a token that can be repeated.

Sooooo... maybe the filter is not regex-based after all.

Reply to this Comment

@Todd,

Its can't be regex, cause in regex, the "." means any character (except line breaks and returns), and in ours, its the literal period. These looks like regex, but don't seem to act that way.

Reply to this Comment

Right, because it'd have to be \. to be a literal period. I guess they went for regex-like and then stopped. IMHO, it'd be better if they just implemented a filter based off regex, but I guess they wanted to keep it simple.

Reply to this Comment

@Ben : btw, I went to that link I posted above and posted a comment at the end of the cfdirectory page and provided a link here. Good discussion regardless. Adobe has a comment approval thing, so it'll be awhile before it shows up.

Reply to this Comment

Okay i ran into a small issue with multiple filters and with office 2007.

If i have my filters set to *.doc|*.docx.... the docx files ARE NOT showing up in the cfdirectory result.

If i swap those two, and make it *.docx|*.doc then both types show up.
Same with xls and xlsx, and i assume ppt and pptx.

Just thought Id share.

-Matthew

Reply to this Comment

This makes sense because I have had to warn other programmers about this in CF. I noticed users stripping the file and taking the last 3 of the file name as the extension. A better way is to use ListLast(file,".") and use the period as a delimiter. I have been doing some work in AS3 and you can do this in an array using indexOf. In any case glad you have a little hack for it now!

Reply to this Comment

@Matthew,

That is just bananas! Was this engine written back when everything had a three-character file extension???

Reply to this Comment

Does anyone know how ignore a file/folder using cfdirectorya action=list? Let's say I want to list all files (recurse) except for files in the "Archive" directory

Reply to this Comment

@Mike D - You would have to do a query of queries to accomplish that. If you are working with a very large recordset you could always dip into Java to accomplish that.

Reply to this Comment

I just tried a filter param like this:

filter="*uploads_frage*.zip"

and gives me
1 10793_uploads_frage4.zip
2 11650_uploads_frage3.zip
3 2715_uploads_frage8.zip
4 2715_uploads_frage9.zip
5 7383_uploads_frage8.zip
6 7383_uploads_frage9.zip
7 7629_uploads_frage29.zip
8 7629_uploads_frage30.zip
9 7845_uploads_frage10.zip
10 7845_uploads_frage17.zip
11 7845_uploads_frage26.zip
12 7845_uploads_frage9.zip
13 Copy of 7383_uploads_frage9.zip

perfect, so * can be used multiple times in same filter. a step closer to regex ;-)
just wanted to share this with you guys.

Reply to this Comment

@Raffael,

Very cool - thanks for sharing. Not sure if I ever tried multiple * characters before.

Reply to this Comment

One cool thing about cfdirectory on Railo: you can use a function as the filter argument. Possibly something for CF 10 as well?
For example:
<cfdirectory action="list" directory="/test/" recurse="true" name="qFiles" filter="#theFilter#" />
<cfdump var="#qFiles#" />
<cffunction name="thefilter" returntype="boolean">
<cfargument name="fullpath" type="string" />
<!--- allow certain extensions --->
<cfif refindNoCase("[/\\]DisallowedDirectory[/\\]", arguments.fullPath)>
<cfreturn false />
<!--- allow certain extensions --->
<cfelseif refindNoCase("\.(swf|jpe?g|gif|png)$", arguments.fullPath)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>

By the way, when you test this code on ACF 8 or 9, it does not throw an error, but instead just returns zero records.

Reply to this Comment

My coworker is using cfdirectory filter to get only the directories named as a language code (using a filter like 'E|F|IT|AF|EL|ES' etc.) and it's behaving really strangely!

For example with the filter above, it wouldn't give us the 'EL' and 'ES' folder because of the initial 'E' folder. I told him to just get ALL the folders without a filter and use a loop to filter them 'manually' using an array of the valid codes, but we found a stupid fix that works great.

By using a DESCENDING order in the filters, we get something like this : 'IT|F|ES|EL|E|AL', and since 'E' filter is always AFTER the 'E*' folders, then we get all the folders we want!

I threw up a little at cfdirectory's filter mode, but it seems to work great in our case. I still feel like we have commited a great sin

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.