Tcl – How to Locate Include File to Source

The Problem

In your Tcl script, you want to source (include) another script that resides the in the same directory. However, all is fine if your scripts are in the current directory. If you execute the main script from a different directory, Tcl complains that the included script is not found.

To demonstrate this problem, create a directory called demo from your home directory and cd to it:

mkdir ~/demo
cd ~/demo

In this directory, create two files:

# library.tcl
proc greet {} {
    puts "Hello, world"
}
# main.tcl
source library.tcl
greet

Now, execute the main script:

tclsh main.tcl

The script works as expected and produces “Hello, world”. However, if you cd to a different directory, say the home directory, and execute that same main script, the result is different:

$ tclsh ~/demo/main.tcl 
couldn't read file "library.tcl": no such file or directory
    while executing
"source library.tcl"
    (file "/home/haiv/demo/main.tcl" line 2)

The problem is the source statement in line 2 of main.tcl looks for the file library.tcl in the current directory, which explains why the it works the first time, but fails the second. The next section will discuss the solution to make it work in both cases.

The Solution

In order for main.tcl to find library.tcl, it needs to look in the directory where main.tcl is and here is the trick:

# main.tcl
source [file dirname [info script]]/library.tcl
greet

The info script command returns the location of the currect script (main.tcl). Next, the file dirname command extracts the directory part. Finally, we append /library.tcl to give the full path to library.tcl. So now, it does not matter where you execute the script from, the main script will always find its library to include

The Revised Solution

I would like to thank michaelhinds for this suggestion:

# main.tcl
source [file join [file dirname [info script]] library.tcl]
greet

This time, we use the file join command to ensure cross-platform compatibility instead of hardcoding using the forward slash (/).

4 thoughts on “Tcl – How to Locate Include File to Source

  1. michaelhinds

    Thanks Hai! I think strictly speaking you should use file join rather than hard coding the “/” (to guarantee cross-platform compatibility)

  2. Halo

    How to i source that is in a different sub-directory for e.g. script is located /a/b/c/test.tcl
    file to source is located in /a/b/d/e/file.tcl. How can i source the file without knowing the absolute path. To give you more info, the files will be located in a CVS repository and will be checked out by the user. In that case /a/b will be unique to the user.
    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s