Ask a Jedi: Getting the current directory

I sometimes like to start the morning off with an easy question. Makes me feel all smarty-pants and stuff. Here is a quickie from Patrick that may actually be news to some folks, so hopefully it will be easy for me - helpful for others.

Hi Ray, me again I have a, maybe silly, question about getting the current directory. I have to get the current directory in which a template resides. But I don't want the full path.

If i run www.example.com/folder/index.cfm i should get "folder" but not path/to/somewhere/in/the/system/folder. I tried with expandpath("./") and getDirectoryFrom Path(ExpandPath(CGI.SCRIPT_NAME)) but this always returns a full path. Any built in function i forgot to try? Thanks for a hint!

This is two issues here. How do I get the directory from a full path, and how do I get the current directory. The first one is simple. The getDirectoryFromPath() function will take any full path and return just the directory. There is also a corresponding getFileFromPath() function.

The second issue is slightly more complicated. ColdFusion has two functions related to getting the current template. They are getBaseTemplatePath() and getCurrentTemplatePath(). I tend to forget which does what, but consider this first example:

<cffunction name="onRequestStart" returnType="boolean" output="true">
   <cfargument name="thePage" type="string" required="true">
   <cfoutput>
   getCurrentTemplatePath()=#getCurrentTemplatePath()#<br>
   getBaseTemplatePath()=#getBaseTemplatePath()#<br>
   <p>
   </cfoutput>      
   <cfreturn true>
</cffunction>

When I run test4.cfm, I get:

getCurrentTemplatePath()=/Users/ray/Documents/Web Sites/webroot/Application.cfc
getBaseTemplatePath()=/Users/ray/Documents/Web Sites/webroot/test4.cfm

The getCurrentTemplatePath refers to the actual file being run right now, which is Application.cfc, and getBaseTemplatePath returns to the main file being executed.

If that sounds a bit unclear, forgive me. As I said, I always forget the difference (one reason I'll fail the CF8 cert probably). In general you are going to want to use getCurrentTemplatePath if you want to consider the file where the actual function is being run.

Comments

@Raymond:

It sounds like he may be wanting to get the directory relative to the webserver, not from the OS path--but I could be wrong.
# Posted By Dan G. Switzer, II | 5/8/08 10:09 AM
I don't know - he said specifically folder - which to me means a full path. Let's see what he says (I pinged him to let him know I blogged it).
# Posted By Raymond Camden | 5/8/08 10:13 AM
@Ray and Patrick

If understand correctly you want to get the directory, relative to your webroot, of the currently executing template right?

For example:

URL:http://localhost/mycfstuff/samples/index.cfm

Full Path:C:\Inetpub\wwwroot\mycf\samples\index.cfm

Want:\mycf\samples\

You can use expandPath("/") to get the path to webroot
C:\Inetpub\wwwroot\

you can use getDirectoryFromPath(getCurrentTemplatePath()) to get the full directory: C:\Inetpub\wwwroot\mycf\samples\

The some simple majik to get just the directory.

right(getdirectoryfrompath(getcurrenttemplatepath()),len(getdirectoryfrompath(getcurrenttemplatepath()))-len(expandpath("/"))+1)

gives you: \mycf\samples\

You have to add the +1 at the end in order to keep the slash in the front.

Perhaps not the most elegant way but from what I understood of your question you get JUST the path from the webroot to your template.

Cheers,
# Posted By Gary Gilbert | 5/8/08 10:13 AM
Oh yeah, and if that's really want he wants I wrote a UDF a while back that will parse a URL:

http://blog.pengoworks.com/index.cfm/2006/9/27/CFM...

This script will parse out the path to in the URL. You could easily modify the code to only generate the path if that's all you wanted as well.
# Posted By Dan G. Switzer, II | 5/8/08 10:13 AM
@Gary:

One problem with the solution you posted is that it may not work in all cases--for example when virtual directories are being used with the webserver. In those cases the URL path is much different than the OS path.
# Posted By Dan G. Switzer, II | 5/8/08 10:15 AM
A related question (more theoretical than anything else, I've just always wondered if this can be done) - what if you have a template that is included by another template (i.e. via CFMODULE, CFINCLUDE, etc.) - is there a way to determine the path of the parent (calling) template? Or retrieve the stack of calling templates up to the base template?

I'm wondering because the CFCATCH exception variable includes the complete calling stack (this is probably not the right term), and I could imagine some potential uses for accessing that info at runtime.

( Note: I'm thinking of something more elegant than throwing an exception and extracting the data from the CFCATCH variable; I write some ugly code, but that seems like overkill. )
# Posted By jdbo | 5/8/08 10:18 AM
@Dan,

Thats very true, but then you could also use the PATH_INFO cgi variable to give you the relative path to the executing page, id does give you the page as well but you could also quite simply remove it.

PATH_INFO=/mycf/samples/index.cfm

But it really depends on what you are looking for as you mentioned in your first post, the os path or the web path
# Posted By Gary Gilbert | 5/8/08 10:19 AM
@Gary:

Just a heads up that not every webserver will populate the cgi.path_info. I believe IIS might be the only webserver that does. You always have to be a bit wary when using CGI variables, since what's returned varies by webserver.
# Posted By Dan G. Switzer, II | 5/8/08 10:23 AM
@jdbo:

Yep. getBaseTagList will give you a list of everyone above you. To get the guy right above you, it would just be the last item.
# Posted By Raymond Camden | 5/8/08 10:24 AM
Just to mix things up a bit, and I've been doing some url rewrites & php lately, what kind of curveball does this throw here(of course in CF)? Where according to the web root we might see

/dir1/dir2/what-im-viewing

but it might actually be

/some/dir/index.cfm

I'm actually not at all familiar with rewrites and ColdFusion, and I am asking this out of curiosity. Would the solutions provided be fore the actual url, or the rewritten url?
# Posted By Trent Richardson | 5/8/08 10:29 AM
I think Patrick is actually looking for this:

<cfset thisDirectory = ExpandPath(".")>
<cfoutput>#getFileFromPath(thisDirectory)#</cfouptut>
# Posted By Steve Withington | 5/8/08 11:28 AM
Just in case people are actually wanting to get the "web path" and not the OS path, I wiped up a little UDF that should return the correct web path:

http://blog.pengoworks.com/index.cfm/2008/5/8/Gett...

This uses the getPageContext() to return the path info--which should be more reliable than CGI.path_info.

@Trent:
This *should* work for virtual or remapped folders as well (since it should be return the path as seen by the browser,) but I have not tested it.
# Posted By Dan G. Switzer, II | 5/8/08 11:34 AM
A clever developer once showed me a handy trick for dealing with paths - and getting certain parts - by using list functions (listFirst,listLast,listGetAt) and passing slashes (back or forward) as a delimiter in the list. As someone else mentioned, it all depends on what you're trying to get, but I have found that trick quite useful.
# Posted By Rachel | 5/8/08 11:37 AM
Hi @ all and thanks for all the hints.
Ray wrote me, i should use listlast(application.directory,"/\"), 'cause i have set this:
<cfset application.Path = ExpandPath(CGI.SCRIPT_NAME)>
<cfset application.Directory = GetDirectoryFromPath(application.Path)>

What i need is the path relative to the executed template.
So if my URL is www.example.com/some/other/folders/index.cfm
I only want folders. The listlast works, but only if i'm in a subdirectory. Calling the listlast from the webroot returns htdocs, of course. But this can be handled.

My problem is, that i don't know if the project i'm currently work on, will be placed in the webroot or in some subfolder(s).
# Posted By Patrick | 5/8/08 12:33 PM
Patrick, I read your comment 3 times and I'm still confused. What do you mean "I only want folders". Maybe you can give us an example of the result you want? Ie a real example. (Url = x, I want y).
# Posted By Raymond Camden | 5/8/08 12:38 PM
Me again. I now tried the UDF from Dan. This exactly what i searched for! Thanks!!
# Posted By Patrick | 5/8/08 12:42 PM
@ Ray

If the URL is www.example.com/shop/products/computers/index.cfm

I want computers. With / or not never mind. (hope this is correct english, i'm german ;))
# Posted By Patrick | 5/8/08 1:12 PM
@Patrick,

Did you see my comment? It gives you just that without having to use a UDF.

I blogged it at http://www.stephenwithington.com

If you use this:

<cfset thisDirectory = ExpandPath(".") />
<cfoutput>#getFileFromPath(thisDirectory)#</cfoutput>

The result is "folder"
# Posted By Steve Withington | 5/8/08 1:17 PM
Ditto Steve. You could also use the code I originally suggested, but add the listLast to get the last folder. Steve's is shorter though.
# Posted By Raymond Camden | 5/8/08 1:23 PM
By the way, it's nice to know this 'simple' blog entry has gotten so much discussion. ;)
# Posted By Raymond Camden | 5/8/08 1:24 PM
@ Steve
Sorry, i missed your post. It's another good solution, of course!
# Posted By Patrick | 5/8/08 1:30 PM
@ray re:getbasetaglist

Thanks! I'd never looked closely at this tag, always having considered it one of the odder additions - now I see how it could be useful, thanks!
# Posted By jdbo | 5/8/08 2:50 PM
@Steve:

The only issue with your solution is it does not work if you're using virutal folders or using a remapping rule. If those are an issue, it works fine.

I wrote the UDF with the intent on working on the actually URL in the browser--which can vary drastically from the OS path.
# Posted By Dan G. Switzer, II | 5/9/08 10:07 AM