Palmer
Palmer

Reputation: 45

How to manipulate components of pathnames in Tcl?

I'm writing a reporting script that's part of a portable testing package. The user can unzip the package anywhere on their system, which is fine, but it means I can't hardcode a path.

Let's say that on my system, this script lives at C:/projects/testpackage/foo/bar/script.tcl. I need to set a variable, packageLocation, the path to /testpackage. In this example, it would be C:/Projects/testpackage. But when the user gets the package, he or she could put it anywhere, like so:

C:/Users/whatever/testpackage.

So, how can I call two levels up from the location of my currently running script? In Batch, I could do

    :: example.bat
    cd %~dp0
    cd ../..
    set packageLocation=%cd%

In Tcl, I'm lost. I know that the current location of the running script can be called as $::argv0. I've tried using cd ../.., but to no avail. It tries to set packageLocation as "../..C:/Projects/testpackage/foo/bar/script.tcl."

Any help is appreciated. Thanks!

Upvotes: 0

Views: 1295

Answers (1)

kostix
kostix

Reputation: 55443

set where [file normalize [file dirname [info script]]]
set parts [file split $where]
set pkgloc [file join {*}[lrange $parts 0 end-2]]

Should do what you want.

It goes like this:

  1. Obtains the directory name of the file from which the current script was read to be evaluated, then normalizes it (replaces ~, .. etc).
  2. Splits obtained full pathname at path separators producing a list of path components.
  3. Extracts a new list from the list of path components containing all them from the beginning except the last two, then joins them back to produce the final name.

If you have Tcl < 8.5, the last line will have to be rewritten:

set last [expr {[llength $parts] - 3}]
set pkgloc [eval [list file join] [lrange $parts 0 $last]]

Upvotes: 4

Related Questions