Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tcl: eval and exec confusing point

Tags:

eval

exec

tcl

I am a little confused by the exec and eval in Tcl. In the following example:

set cmd "mkdir new_folder";
exec $cmd

doesn't work with error message : couldn't execute "mkdir new_folder" no such file or directory. and with eval it works

set cmd "mkdir new_folder";
eval exec $cmd

I also tried this way:

set cmd_1 "mkdir";
set cmd_2 "new_folder"
exec $cmd_1 $cmd_2

It also works well. so what's the reason?

like image 563
Chris Bao Avatar asked Oct 28 '25 09:10

Chris Bao


2 Answers

Where you really have to watch out is when one of your parameters contains whitespace. In that case, eval won't know what to do:

% set cmd "mkdir 'dir with spaces'"
mkdir 'dir with spaces'
% eval exec $cmd
% exec ls -l
total 20
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 'dir
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 spaces'
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 with

What you really want to do is to use a list. Then Tcl understands exactly what the separate elements are

% set cmd [list mkdir "dir with spaces"]
mkdir {dir with spaces}
% exec {*}$cmd
% exec ls -l
total 24
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 'dir
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:53 dir with spaces
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 spaces'
drwxr-xr-x 2 glennj glennj 4096 Feb 12 07:51 with
like image 157
glenn jackman Avatar answered Oct 31 '25 11:10

glenn jackman


As it is already implied in your own comment, the issue is with the interpretation of parameters. If you still want to have the command in single string you could use expansion operator {*}.

set cmd "mkdir new_folder"
exec {*}$cmd ;# Tcl 8.5 or higher
eval exec $cmd ;# alternative solution

This does not only pertain to exec command. The general rule is: if a command accepts multiple paramaters, and say are stored in a variable params, when you call the command the paramaters have to be expanded: cmd {*}$params. Thus, these following scripts are equivlent

cmd param1 param2

and

set params "param1 param2"
cmd {*}$params
like image 36
DurgaDatta Avatar answered Oct 31 '25 10:10

DurgaDatta



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!