Version 10 of Determining the Applications Root Directory

Updated 2003-03-03 10:35:01

An application might be written that sources needed files, makes use of images files, etc. All the files are relative to the physical location of the actual program.

Problem How do you determine the directory (without hardcoding it in the program) that contains your executable? This isn't as easy as you might first think. What if the executable is executed via an alias (UNIX) or shortcut (Windows). Or perhaps a symbolic link (UNIX) to the executable is used.

Solution This bit of code will do the trick:

  if {![catch {file readlink $::argv0} APPLICATION_HOME ]} {
    set APPLICATION_HOME [file dirname $APPLICATION_HOME]
  } else {
    set APPLICATION_HOME [file dirname $::argv0]
  }
  set origPwd [pwd]
  cd $APPLICATION_HOME
  set APPLICATION_HOME [pwd]
  cd $origPwd

See Making a Path Absolute for a related discussion

Marty Backe


That doesn't seem to handle multiple (a->b->file) symlinks or relative symlinks ( ln -s ../rje/file . ). RS and others posted code to answer this question on comp.lang.tcl, and this is a modification of the code in that discussion:

 set OldPWD [pwd]

 set scriptpath $argv0
 set workdir [file dirname $argv0]

 while {![catch {file readlink $scriptpath} res]} {
     cd $workdir
     set scriptpath [ file join [pwd] $res ]
     set workdir [ file dirname $scriptpath ]
 }
 set scriptpath [file dirname $scriptpath ]
 cd $OldPWD

 # now you can ref those other files in that directory...
 source [file join $scriptpath some_other_file]

My modified version was only tested under Tcl 8.3.4 on Linux. Of course, it does not detect looped smylinks ( a->b->a ).

StephenHill


If the symlinks are looped, how did the program start in the first place?


If you are using a Starkit, the root directory is contained in the starkit::topdir variable

    package require starkit
    puts stderr "root directory = $starkit::topdir"

FW: Of course, if you're satisfied with it only working if the application is invoked directly, then you can just invoke this code to retrieve the application root:

  file dirname [info script]

US: See also: