Fullpath of current TCL script
Asked Answered
W

5

16

Is there a possibility to get the full path of the currently executing TCL script?

In PHP it would be: __FILE__

Weigle answered 1/10, 2010 at 11:8 Comment(0)
R
8

You want $argv0

Rosanne answered 1/10, 2010 at 14:27 Comment(2)
if accessing from a procedure, either define argv0 as global, or fully qualify it as $::argv0Mueller
Note that the global argv0 variable is a feature of tclsh and wish (and tclkit too) and not of Tcl in general. It's very common though; the support function Tcl_Main implements it for you…Mev
B
16

Depending on what you mean by "currently executing TCL script", you might actually seek info script, or possibly even info nameofexecutable or something more esoteric.

Burl answered 1/10, 2010 at 15:16 Comment(0)
S
15

The correct way to retrieve the name of the file that the current statement resides in, is this (a true equivalent to PHP/C++'s __FILE__):

set thisFile [ dict get [ info frame 0 ] file ]

Psuedocode (how it works):

  1. set thisFile <value> : sets variable thisFile to value
  2. dict get <dict> file : returns the file value from a dict
  3. info frame <#> : returns a dict with information about the frame at the specified stack level (#), and 0 will return the most recent stack frame NOTICE: See end of post for more information on info frame.

In this case, the file value returned from info frame is already normalized, so file normalize <path> in not needed.

The difference between info script and info frame is mainly for use with Tcl Packages. If info script was used in a Tcl file that was provided durring a package require (require package <name>), then info script would return the path to the currently executing Tcl script and would not provide the actual name of the Tcl file that contained the info script command; However, the info frame example provided here would correctly return the file name of the file that contains the command.

If you want the name of the script currently being evaluated, then:

set sourcedScript [ info script ]

If you want the name of the script (or interpreter) that was initially invoked, then:

set scriptAtInvocation $::argv0

If you want the name of the executable that was initially invoked, then:

set exeAtInvocation [ info nameofexecutable ]

UPDATE - Details about: info frame

Here is what a stacktrace looks like within Tcl. The frame_index is the showing us what info frame $frame_index looks like for values from 0 through [ info frame ].

Calling info frame [ info frame ] is functionally equivalent to info frame 0, but using 0 is of course faster.

There are only actually 1 to [ info frame ] stack frames, and 0 behaves like [ info frame ]. In this example you can see that 0 and 5 (which is [ info frame ]) are the same:

frame_index: 0 | type = source | proc = ::stacktrace | line = 26 | level = 0 | file = /tcltest/stacktrace.tcl | cmd = info frame $frame_counter
frame_index: 1 | type = source | line = 6 | level = 4 | file = /tcltest/main.tcl | cmd = a
frame_index: 2 | type = source | proc = ::a | line = 2 | level = 3 | file = /tcltest/a.tcl | cmd = b
frame_index: 3 | type = source | proc = ::b | line = 2 | level = 2 | file = /tcltest/b.tcl | cmd = c
frame_index: 4 | type = source | proc = ::c | line = 5 | level = 1 | file = /tcltest/c.tcl | cmd = stacktrace
frame_index: 5 | type = source | proc = ::stacktrace | line = 26 | level = 0 | file = /tcltest/stacktrace.tcl | cmd = info frame $frame_counter

See: https://github.com/Xilinx/XilinxTclStore/blob/master/tclapp/xilinx/profiler/app.tcl#L273

Shive answered 12/6, 2014 at 5:43 Comment(6)
info frame 0 should suffice instead of the longer info frame [ info frame ]. The zero refers to the current frame whereas the innermost info frame without arguments would return the number of the current frame.Tasimeter
Hi @cfi, this is a little counter intuitive, but [ info frame ] really starts with 1 and goes to [ info frame ]. 1 being the originating call and [ info frame ] being the most recent call. However, if you pass 0 into info frame, then you get the equivalent of [info frame [info frame]], which is the most recent call.Shive
When set thisFile [ dict get [ info frame 0 ] file ] is used in tcl script in vmd, I got key "file" not in dictionary. Could you help to suggest what to do here?Abutment
I’d start to debug with this: set frame [ info frame 0 ]; puts $frame See if the dict has the correct keys.Shive
@Shive I get type eval line 1 cmd {info frame 0 } level 0. Could you help to suggest how to go on ? Many thanks !Abutment
This return dict doesn't have a file key and suggests that it was not invoked by a file, but was instead invoked by a Tcl command being entered (evaluated) directly. You could add a check for the file key and if it doesn't exist then issue a message that the there was no-file: set thisFile [expr {[dict exists [info frame 0] file] ? [dict get [info frame 0] file] : "no-file"}]Shive
R
8

You want $argv0

Rosanne answered 1/10, 2010 at 14:27 Comment(2)
if accessing from a procedure, either define argv0 as global, or fully qualify it as $::argv0Mueller
Note that the global argv0 variable is a feature of tclsh and wish (and tclkit too) and not of Tcl in general. It's very common though; the support function Tcl_Main implements it for you…Mev
R
4

You can use [file normalize] to get the fully normalized name, too.

file normalize $argv0
file normalize [info nameofexecutable]
Rejoice answered 1/10, 2010 at 15:51 Comment(0)
W
-3

seconds after I've posted my question ... lindex $argv 0 is a good starting point ;-)

Weigle answered 1/10, 2010 at 11:14 Comment(1)
I think you'll be disappointed with that. You'll get the first argument after the filename. If you do "tclsh foo.tcl one two" argv will be a list like ["one" "two"]Mueller

© 2022 - 2024 — McMap. All rights reserved.