What syntax should we use ? cmd2 has to be started only when cmd1 is
finished.
NOTE : cmdx do not use pipes !!
Thanks !
Raymond Ripp
The easiest answer by far is to use multiple calls to [exec] e.g.:
exec cmd1
exec cmd2
.
.
Solutions with multiple commands on a single line could be possible,
but I am too lazy to try what separator and escaping is required there
(especially because using multiple exec calls works just fine)
Mark
The semicolon as command separator is a feature of some (most?) SHELL.
Exec by default does not call the SHELL, but executes the command
directly. In order to use SHELL features, you need to call the SHELL.
Unix:
exec sh -c "cmd1 ; cmd2 ; cmd3 ..."
Windows:
exec cmd /c "cmd1 ; cmd2 ; cmd3 ..."
But the easiest solution is as already pointed out in another message in
this thread to exec the commands separately.
R'
You can probably do:
exec sh -c {cmd1 ; cmd2 ; cmd3}
But, yes, multiple exec calls would have the advantage not having to
play exotic quoting games should cmd1, cmd2, or cmd3 also need
parameters passed as well.
>
> Mark
>
--
Robert Heller -- 978-544-6933
Deepwoods Software -- Download the Model Railroad System
http://www.deepsoft.com/ -- Binaries for Linux and MS-Windows
hel...@deepsoft.com -- http://www.deepsoft.com/ModelRailroadSystem/
Note that the windows example demonstrates nicely why multiple exec-s
are easier. In windows' cmd.exe ";" is not a command separator. So the
windows example will probably not do what was intended.
Mark
Also, the shell in this case is "tclsh". Tclsh is a shell. If you can
avoid it, don't use tclsh to invoke the login shell because tclsh
inherits the system commands (but overrides those with the same name).
Maybe someone can explain when and why to use [exec]. It might have
more to do with running in a script (not an interactive shell), or
wanting to capture a result/side effect.
D'oh!
R'
huh? How did the *login* shell enter the game?
tclsh doesn't inherit anything, but if it is faced with an undefined
command name, it may (as per default "unknown"-handler) look for
programs on the PATH and call exec on them for you with some specific
redirections, so interactive programs started that way work as
expected. (imagine running vi and capturing its output as exec does
by default - not very useful)
> Maybe someone can explain when and why to use [exec]. It might have
> more to do with running in a script (not an interactive shell), or
> wanting to capture a result/side effect.
yes, exactly both of those.
A previous message said:
You can probably do:
exec sh -c {cmd1 ; cmd2 ; cmd3}
> tclsh doesn't inherit anything, but if it is faced with an undefined
> command name, it may (as per default "unknown"-handler) look for
> programs on the PATH and call exec on them for you with some specific
> redirections, so interactive programs started that way work as
> expected. (imagine running vi and capturing its output as exec does
> by default - not very useful)
I wasn't thinking about interactive programs, but even those would be
executed through the unknown mechanism unless the global variable
auto_noexec is defined (although this would likely be a mistake).
If the OP was interested in results, it wasn't mentioned.
> > Maybe someone can explain when and why to use [exec]. It might have
> > more to do with running in a script (not an interactive shell), or
> > wanting to capture a result/side effect.
>
> yes, exactly both of those.
Question is: is it always better to use [exec]? It depends. Tcl
scripts could break at any time for many reasons. However, any shell's
(sh, bash, csh, etc.) script could fail for many of the same reasons,
so if the primary purpose of the script is to invoke operating system
commands, maybe avoid using [exec] and write the script as if the OS
commands are built-in commands.
If I need to call another program, I *have* to use 'exec' in scripts.
Only in interactive sessions TCL exec's unknown commands automagically.
So there is no way around exec.
| Tcl scripts could break at any time for many reasons. However, any
| shell's (sh, bash, csh, etc.) script could fail for many of the same
| reasons, [...]
Of course exec'd programs can fail like any other TCL command/proc, this
is why we have 'catch'.
| [...] so if the primary purpose of the script is to invoke operating
| system commands, maybe avoid using [exec] and write the script as if
| the OS commands are built-in commands.
Could you elaborate?
This proc will simply fail, interactive or not:
proc exec_ls {} {
return [ls]
}
exec_ls
=> invalid command name "ls"
While 'ls' entered on the interactive prompt will call the external
program 'ls'.
R'
Right, see below.
> | Tcl scripts could break at any time for many reasons. However, any
> | shell's (sh, bash, csh, etc.) script could fail for many of the same
> | reasons, [...]
>
> Of course exec'd programs can fail like any other TCL command/proc, this
> is why we have 'catch'.
My comment was about why maybe not to do this:
exec sh -c {cmd1 ; cmd2 ; cmd3}
Because tclsh is already a shell. And, as I explain below, I stupidly
read the [unknown] manpage instead of looking at my own code for
examples.
> | [...] so if the primary purpose of the script is to invoke operating
> | system commands, maybe avoid using [exec] and write the script as if
> | the OS commands are built-in commands.
>
> Could you elaborate?
>
> This proc will simply fail, interactive or not:
> proc exec_ls {} {
> return [ls]
> }
> exec_ls
> => invalid command name "ls"
>
> While 'ls' entered on the interactive prompt will call the external
> program 'ls'.
That is weird. I was just reading from the [unknown] manpage, which
explained what would happen if an internal command was not found.
Looking through my own code, I always use [exec cmd].
I'm not sure if I'm misreading the manpage or what. Here is what it
says (8.5) sorry for the length:
"The default implementation of unknown behaves as follows. It first
calls the auto_load library procedure to load the command. If this
succeeds, then it executes the original command with its original
arguments. If the auto-load fails then unknown calls auto_execok to
see if there is an executable file by the name cmd. If so, it invokes
the Tcl exec command with cmd and all the args as arguments. If cmd
can't be auto-executed, unknown checks to see if the command was
invoked at top-level and outside of any script. If so, then unknown
takes two additional steps. First, it sees if cmd has one of the
following three forms: !!, !event, or ^old^new?^?. If so, then unknown
carries out history substitution in the same way that csh would for
these constructs. Finally, unknown checks to see if cmd is a unique
abbreviation for an existing Tcl command. If so, it expands the
command name and executes the command with the original arguments. If
none of the above efforts has been able to execute the command,
unknown generates an error return. If the global variable auto_noload
is defined, then the auto-load step is skipped. If the global variable
auto_noexec is defined then the auto-exec step is skipped. Under
normal circumstances the return value from unknown is the return value
from the command that was eventually executed."
This is the second time the [unknown] command has surprised me. I
think I'm gonna make an effort to just auto_disable this command for
my own stuff.
Sorry for the confusion.
Ok, makes sense now. :-)
R'
I think this text is plain wrong. The auto_execok check is *inside* the
conditional for "top-level/outside of any script/interactive".
Cf. 'info body unknown' in a fresh interpreter.
% info body unknown
--<snip-snip>--
if {([info level] == 1) && ([info script] eq "") && [info exists tcl_interactive] && $tcl_interactive} {
if {![info exists auto_noexec]} {
set new [auto_execok $name]
if {$new ne ""} {
set redir ""
if {[namespace which -command console] eq ""} {
set redir ">&@stdout <@stdin"
}
uplevel 1 [list ::catch [concat exec $redir $new [lrange $args 1 end]] ::tcl::UnknownResult ::tcl::UnknownOptions]
dict incr ::tcl::UnknownOptions -level
return -options $::tcl::UnknownOptions $::tcl::UnknownResult
}
}
--<snip-snip>--
Time for a documentation change request in the tracker?
R'