ColdFusion Path Usage And Manipulation Overview

Posted March 26, 2007 at 8:40 AM

Tags: ColdFusion

Just a quick little ColdFusion path explanation. Sometimes I get confused about some path stuff, so I thought I would jot it down to help imprint in my grey matter. All path demonstrations use the following directory structure:

./index.cfm
./sub/sub.cfm

Additionally, we never call the sub.cfm page directly. Sub.cfm is included by index.cfm so that we can see how included sub-directories work with ColdFusion paths:

ExpandPath()

This creates an absolute path using a path relative to the directory of the currently executing page. This does NOT necessarily mean the currently executing template. If we run:

 Launch code in new window » Download code as text file »

  • #ExpandPath( "./" )#

... in both of the template, index.cfm and sub.cfm respectively give us:

D:\sites\kinky_solutions\site_v1\testing\paths\
D:\sites\kinky_solutions\site_v1\testing\paths\

Notice that regardless of the template from which it was called, ExpandPath() gives us an absolute path based on index.cfm, the currently executing page. This is one of the trickiest things for me when I deal with uploading files. I always have to remember that ExpandPath() is NOT relative to the action page I am processing - it is relative to my front controller.

GetCurrentTemplatePath()

This returns the absolute path of the currently executing template. The currently executing template is the one in which the code is being called from, not necessarily the path in the browser URL. If we run:

 Launch code in new window » Download code as text file »

  • #GetCurrentTemplatePath()#

... in both of the templates, index.cfm and sub.cfm respectively give us:

D:\sites\kinky_solutions\site_v1\testing\paths\index.cfm
D:\sites\kinky_solutions\site_v1\testing\paths\sub\sub.cfm

This is a really useful function when you need to get a path relative to the current template. To get the directory of this template, you can always use GetDirectoryFromPath(). If we run:

 Launch code in new window » Download code as text file »

  • #GetDirectoryFromPath(
  • GetCurrentTemplatePath()
  • )#

... in both templates, index.cfm and sub.cfm respectively give us:

D:\sites\kinky_solutions\site_v1\testing\paths\
D:\sites\kinky_solutions\site_v1\testing\paths\sub\

This combination of ColdFusion methods can help us get "ExpandPath" functionality bases on the currently executing template, NOT the currently executing page.

GetBaseTemplatePath()

This returns the absolute path the base template. This is the path of the template that maps to the currently executing page. If we run:

 Launch code in new window » Download code as text file »

  • #GetBaseTemplatePath()#

... in both templates, index.cfm and sub.cfm respectively give us:

D:\sites\kinky_solutions\site_v1\testing\paths\index.cfm
D:\sites\kinky_solutions\site_v1\testing\paths\index.cfm

As you case see, it gives us the absolute path of index.cfm (the currently executing page) regardless of which template it is called from. This is akin to running:

 Launch code in new window » Download code as text file »

  • #ExpandPath( CGI.script_name )#

... which will get an absolute path to the currently executing page.

GetDirectoryFromPath()

This takes a path of any kind and returns the a path that maps to the final directory in the given path. This is a utility function and does not rely on an existing path. If we run:

 Launch code in new window » Download code as text file »

  • #GetDirectoryFromPath( "/test/page.cfm" )#

... we get:

"/test/"

We just made up the path "/test/page.cfm" to prove that this has nothing to do with the physical file structure. This method will always leave a trailing slash and will not check to see if the current path is a directory. So, be caution, if you run:

 Launch code in new window » Download code as text file »

  • #GetDirectoryFromPath( "/I_AM_A_DIRECTORY" )#

... and do NOT include a trailing slash, it will return:

"/"

... because it doesn't care what is actually at the end of the given path if it is not a slash. So basically, this function removes every trailing character until it hits a slash or runs out of characters and then returns a path with a trailing slash.

GetFileFromPath()

This takes a path of any kind and returns the file at the end of the path. If we run:

 Launch code in new window » Download code as text file »

  • #GetFileFromPath( "/test/page.cfm" )#

... we get:

page.cfm

In this case, we used an obvious file name; however, this method really only returns everything it can starting at the end of the given path until it hits a slash. If we ran:

 Launch code in new window » Download code as text file »

  • #GetFileFromPath( "/test" )#

... where "test" is actually a directory, it will still return:

"test"

... since it is the most appropriate choice for a page (the path element located after the final path slash).

GetTempDirectory()

This gets the absolute path of the directory that ColdFusion uses for temporary files. This can be handy for uploading files:

 Launch code in new window » Download code as text file »

  • <cffile
  • action="UPLOAD"
  • filefield="file"
  • destination="#GetTempDirectory()#"
  • />

This will upload the given file into the temp directory.

GetTempFile()

Creates a temporary file (.tmp file) in a directory whose name starts with (at most) the first three characters of the given prefix. What took me a while to understand is that this actually created the physical file, it doesn't just create the file path. I suppose it does this so that no two calls to the same directory one after the other will return the same file path (that would be conflicting).

This can be nicely used in conjunction with GetTempDirectory():

 Launch code in new window » Download code as text file »

  • <cfset strPath = GetTempFile(
  • GetTempDirectory(),
  • "temp"
  • ) />

This will create a .TMP file in ColdFusion's temp file directory and try to use given the prefix. Now, the help docs say that this will use at most the first three characters of the prefix, but in my experience, this method usually uses the entire passed in prefix regardless of length.

Traversing A Path

There is nothing built into ColdFusion that makes traversing a file path very intuitive. In order to move up the directories in a path, I usually use one of three methods: List manipulation, a combination of path methods, or a regular expression.

If you look at a list, it's pretty much a path with the slash as the list item separator. Using this view, you can move up a directory by removing the last two items in the path - remember, the last item in the path is the file. This however can be awkward and if the last element is a slash (there is no file), list manipulation will not use the final empty element as a list item.

I find it best to use a combination of path methods to move up a directory:

 Launch code in new window » Download code as text file »

  • #GetDirectoryFromPath(
  • GetDirectoryFromPath(
  • GetCurrentTemplatePath()
  • ).ReplaceFirst( "[\\\/]{1}$", "" )
  • )#

This gets the current template path. Then, it gets the current directory of that path. Remember, GetDirectoryFromPath() always leaves us with a trailing slash. I then use a regular expression to delete that final slash. Then, I call GetDirectoryFromPath() on the resultant slash. This returns the path to the parent directory.

Then, there is the regular expression approach:

 Launch code in new window » Download code as text file »

  • #GetDirectoryFromPath(
  • GetCurrentTemplatePath()
  • ).ReplaceFirst(
  • "([^\\\/]+[\\\/]){1}$", ""
  • )#

This takes gets the directory of the current template path and then removes a single path item and trailing slash from the resultant path. If you want to move up more than one directory, you can replace the {1} with a {N} where N is the number of directories you want to move up in the path. This method is nice because it is short and can handle multiple directories in a single command. However, if you are super concerned with performance, running this regular expression will be slower than running the combo-option several times in a row. And, the more directories you want to move up in the path, the slower the regular expression becomes.

CGI Paths

The CGI object gives us several paths to work with.

CGI.cf_template_path

This gives us the absolute path of the currently executing page. This is the same as running:

 Launch code in new window » Download code as text file »

  • #ExpandPath( CGI.script_name )#

CGI.path_translated

This also returns the absolute path of the currently executing page. I am not sure what is the difference between this and cf_template_path.

CGI.script_name

This returns the web-page that is currently being executed.

So that's how ColdFusion paths work and a bit on how they can be manipulated. I hope that helps.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page





Reader Comments

Mar 26, 2007 at 10:46 AM // reply »
92 Comments

Amazing there are no comments for this but maybe because its written so well. For those that have read this please bookmark it! Ben's work with programmatic configuration has done wonders for me. I've been able to have my applications figure out all my file paths so I don't have too and it was possible using these functions. They are very handy. Sorry I didn't notice this earlier Ben as I was on vacation. Bookmarked!


Mar 26, 2007 at 10:50 AM // reply »
6,516 Comments

@Javier,

Thanks a lot for the kind words :) No worries about the bookmarking - it was only posted a few hours ago ;) Glad all the programmatic config stuff is working out for you.


Mar 26, 2007 at 11:10 AM // reply »
92 Comments

Doh! I thought this was one of your older posts. You see I go through your blog daily and I thought when I opened this in a new tab that it was a post from a few days ago, not this morning. I didn't get a chance to read it right away. Still though what I said about bookmarking this still stands! :) Well done.


Mar 26, 2007 at 2:42 PM // reply »
15 Comments

Pretty nice Ben.

I already have a similar thing for myself written down in my "CF cookbook".


Mar 26, 2007 at 2:48 PM // reply »
6,516 Comments

Sounds tasty ;)


Jul 25, 2007 at 10:11 PM // reply »
2 Comments

Awesome regex for traversing up paths structures, thanks!


Dec 20, 2007 at 4:44 PM // reply »
1 Comments

I'm assuming this only works on Windows and not Linux or Unix?


Dec 20, 2007 at 4:48 PM // reply »
6,516 Comments

@Jim,

These are ColdFusion functions - they should be system independent (I think)? I know that there used to be some issues with the slashes, but I believe ColdFusion has done a better job of abstracting that in the most recent versions.


Jun 14, 2008 at 3:02 AM // reply »
5 Comments

correct these work on linux as well....

just make sure that you have permissions to write to the directory on the linux box....something you not even think twice about when using windows unless you have it locked down...


Oct 7, 2008 at 7:43 PM // reply »
2 Comments

Ben... Ben... dude... Thank you!

#GetDirectoryFromPath(
GetCurrentTemplatePath()
).ReplaceFirst(
"([^\\\/]+[\\\/]){1}$", ""
)#

The getDirectoryFromPath with the regex to delete.... Ohh Thank you!


Oct 8, 2008 at 8:32 AM // reply »
6,516 Comments

@John,

Glad you like :)


Mar 10, 2009 at 11:14 AM // reply »
6 Comments

Ben,
I'm working with a few application pages, and always want the root application page to be able to find configuration settings relative to its path when sent a reload param through the URL no matter where it's executed in the app. From what I can tell, all of the above functions use a path relative to the currently executing template. After digging around I've found the following Java that seems to reliably return the path of the application page it's on:

<cfset variables.thisPage = getPageContext().getFusionContext().getPagePath()>
<cfset variables.thisPagePath = getDirectoryFromPath(variables.thisPage)>

Is this the only way to get the path of a page, whether it's included somewhere or not? Is it as reliable as it seems?

I realize this is a rather old post, but a good one as always.


Mar 17, 2009 at 10:14 AM // reply »
6,516 Comments

@Ted,

Usually, when I need to always have a handle on a particular set of files, I put that code in the Application.cfc / cfm. This way, no matter what page gets calls, the Application file will be executed first and I can grab the files at known relative paths.

From within the Application.cfc, I use:

GetCurrentTemplatePath()

This always returns the full path of the Application.cfc file no matter what template the user requested.


Apr 27, 2009 at 8:46 PM // reply »
1 Comments

Thank you. This is really helpful.

There is a problem with this comment box, it keeps getting longer and longer! (Using Firefox 2.0)


Apr 29, 2009 at 8:03 AM // reply »
6,516 Comments

@Chuck1411,

Thanks. Yeah, someone else mentioned the comment box issue. I will try to debug it. I cannot replicate it with my Firefox, so it will be hard to debug.


Jun 16, 2009 at 5:21 AM // reply »
1 Comments

super super helpful thanks


Aug 11, 2009 at 1:36 PM // reply »
23 Comments

Very useful. Thanks.


Tom
Oct 9, 2009 at 10:37 AM // reply »
2 Comments

I hope this is not off topic, but one thing that I have not been able to get my arms around is the best practice for storing and accessing custom tags when you can't put them in the cf custom tag folder.

Ideally, I could have a custom tag folder in my application that would work the same way as the cf custom tag folder (automatic recursive searchers in sub directories). But even if I can't I would like to have a custom_tag that I could refer to no matter what template was running.

Is there a way using what you have provided above for doing this? Using cfmodule or cfimport to access them in a common manner (without having to consider the location of the currently running page).

Thanks in advance for your thoughts.

Tom


Oct 9, 2009 at 3:45 PM // reply »
6,516 Comments

@Tom,

Custom tags paths are a bit different from the stuff I have outlined. What version of ColdFusion are you running? If you are running CF8, you can set up a per-application custom tag pathing.

If not, you can always use CFImport to import the custom tag paths... or CFModule to provide a template path to the given custom tag.


Tom
Oct 12, 2009 at 10:57 AM // reply »
2 Comments

Ben - Thanks for you response. I am using CF8 and have setup an application specific mapping to the root of my app. Thank you for the suggestion.

So now I can use cfmodule and call the custom tag with an absolute path "/app/custom_tags/my_custom_tag.cfm". It seems to be working like a charm.


Oct 15, 2009 at 2:06 PM // reply »
6,516 Comments

@Tom,

Awesome dude!! Yeah, the app-specific mappings introduced in ColdFusion 8 are fantastic!


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 22, 2009 at 1:56 AM
Learning ColdFusion 9: Using CFQuery In CFScript Can Enable SQL Injection Attacks
Why adobe would give you script equivalent of cfquery is beyond me. I love cfquery tag because it helps me wriite clean sql, and get away from the horrible jdbc queries If I wanted to write javali ... read »
Nov 22, 2009 at 1:45 AM
Streaming Text Using ColdFusion's CFContent Tag And The Variable Attribute
The reason you would want to do this is to stream. Ack json/xml files to ria clients I used thus technique before because putting json in response stream causes debugging info to come thru As well a ... read »
Nov 21, 2009 at 6:47 PM
Hal Helms - Real World Object Oriented Development, Sarasota - Day Five
@charlie griefer, Thank you.. ... read »
Nov 21, 2009 at 5:15 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jose Galdamez, Oh heh yeah I didn't paste the whole code. I should have defined the vars -- my bad. It's fixed thou. Thanks. ... read »
Nov 21, 2009 at 4:49 PM
Styling The ColdFusion 8 WriteToBrowser CFImage Output
Great work yet again Ben! Whilst I didn't use this whole code, I copied some of your regex code for a similar problem with the lack of an alt attribute and unescaped ampersands in CFIMAGE for Railo 3 ... read »
Nov 21, 2009 at 1:13 PM
My First ColdFusion Builder Extension - Encrypting And Decrypting CFM / CFC Files
@Ben, Because I am pedantic, I just want to make sure that everyone knows there is absolutely no encryption going on. There is only encoding and obfuscation. The cfencode tool only obfuscates your C ... read »
Nov 21, 2009 at 12:28 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jody I can't seem to get your code sample to work. If you are still having problems, try this code out and see if it gets you what you wanted. <!--- Comma delimited list with various duplicates ... read »
Nov 21, 2009 at 11:03 AM
Groovy Operator Overloading Does Not Work In The ColdFusion Context
Hi Ben, Thanks for this informative post. Now I am reading ur old posts too ... read »