ColdFusion Path Usage And Manipulation Overview
Posted March 26, 2007 at 8:40 AM
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
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!
@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.
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.
Pretty nice Ben.
I already have a similar thing for myself written down in my "CF cookbook".
Sounds tasty ;)
Awesome regex for traversing up paths structures, thanks!
I'm assuming this only works on Windows and not Linux or Unix?
@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.
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...
Ben... Ben... dude... Thank you!
#GetDirectoryFromPath(
GetCurrentTemplatePath()
).ReplaceFirst(
"([^\\\/]+[\\\/]){1}$", ""
)#
The getDirectoryFromPath with the regex to delete.... Ohh Thank you!
@John,
Glad you like :)
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.
@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.
Thank you. This is really helpful.
There is a problem with this comment box, it keeps getting longer and longer! (Using Firefox 2.0)
@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.
super super helpful thanks
Very useful. Thanks.
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
@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.
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.
@Tom,
Awesome dude!! Yeah, the app-specific mappings introduced in ColdFusion 8 are fantastic!



