I've been working with TCL for some time now, and I have spent a long time trying to do the following (it seems easy and I think it should be, but I can't get it right):
I need to execute an external program by means of a tcl script. For that, I use the exec
command. For using this external program, I need to input a variable amount of files. If I called this program straight from a cmd window, it would be something like:
C:\>myprogram -i file1 -i file2 -i file3 (etc., etc.)
However, when trying to implement this in a dynamic/variable way through tcl I get into trouble. The way I do it is by storing in some variable myvar all the "-i filex
" I need (done in a loop), and then pass that as a parameter to the exec
command. It would look something like:
exec myprogram $myvar
Doing that apparently creates some issues, because this myprogram fails to "see" myvar. I'm guessing that there is some sort of hidden terminator or some clash of different types of arguments that makes that in the end the exec command "sees" only myprogram.
So, my question is, does anyone know how to insert variable arguments into a call to exec
?
Variables. Variables in tcl can be defined with the command set and the value can be used with $variable_name . Arrays can be indexed with arbitrary names in (). Curly braces are used to separate variable names from following characters.
The exec command runs programs from your Tcl script. [*] For example: [*] Unlike other UNIX shell exec commands, the Tcl exec does not replace the current process with the new one.
Uplevel returns the result of that evaluation. If level is an integer then it gives a distance (up the procedure calling stack) to move before executing the command. If level consists of # followed by a number then the number gives an absolute level number. If level is omitted then it defaults to 1.
Environment variables are available to Tcl scripts in a global associative array env . The index into env is the name of the environment variable. The command puts "$env(PATH)" would print the contents of the PATH environment variable.
You can use {*} or eval. See this question for example.
Specializing for your case:
exec myprogram {*}$myvar
eval [list exec myprogram] [lrange $myvar 0 end]
# Or...
eval [linsert $myvar 0 exec myprogram]
That's right, the old version is ugly (or non-obvious, or both). Because of that, people tended to write this instead:
eval exec myprogram $myvar
but that was slower than expected (OK, not so relevant when running an external program!) and has hazards when $myvar
isn't a canonically-formatted list due to the way that eval
works. It used to catch out even experienced Tcl programmers, and that's why we introduced new syntax in 8.5, which is specified to be surprise-free and is pretty short too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With