[Richard Suchenwirth] will have to exercise Tcl with colleagues who are familiar with the Bourne shell (/bin/sh - see [Tcl heritage] for the influences it had on Tcl!), and one task will be to prelace /bin/sh scripts with equivalent Tcl scripts. To make this migration easier, I am planning to introduce some syntactic sugar ([Salt and sugar]), so familiar built-ins can still be used. Most simply with ''[interp] alias'': interp alias {} echo {} puts stdout interp alias {} read {} gets stdin ;# if we don't need the real [read] # interp alias {} whoami {} subst $::tcl_platform(user) # raises cryptic error message when called with args, hence: proc whoami {} {set ::tcl_platform(user)} interp alias {} -r {} file readable interp alias {} -w {} file writable interp alias {} -x {} file executable Note however that ''echo'''s output cannot be redirected to a file, or through a pipe. Things like foo=`echo $bar | grep "^grill"` would have to be restructured: set foo [exec grep ^grill <<$bar] which also has its charms, but needs habituation. (On the other hand, a Tcl'er would prefer [regexp] anyway...) Another difference is the exit status - if ''grep'' can't find a thing, it still raises no direct error in /bin/sh, but you can check the exit status with the special variable $? afterwards. ---- The following one-liner emulates a frequently used part of /bin/sh's ''test'' command: proc -f name {expr {[file exists $name] && [file type $name]=="file"}} This way, /bin/sh code written like this: if [ -f $filename ] ... needs no rewriting - but be aware that this is not a complete emulation of ''test''s switches, so if [ $# -ne 1 ] ... would have to rewritten in [expr] syntax (braced condition, C operators), but we even emulate the Perlish special variable ?# : set # [llength $argv] if {${#} != 1 } ... ---- This fills most of the shell special variables: # Create some shellish variables: proc sh'specials {} { global argv set ::0 $::argv0 set n 0 foreach i $argv { set t [lindex $argv $n] set ::[incr n] $t } set ::# [llength $argv] set ::\$ [pid] set ::? 0 ;# exit status of last command } The following emulates the behavior that errors are not propagated, but may be detected from the special $? variable: proc ! args { if [catch {eval exec $args} res] { if {[lindex $::errorCode 0]=="CHILDSTATUS"} { set ::? [lindex $::errorCode 2] } } set res } proc !! args {puts $args;eval ! args} ---- [Tcl and other languages] - [Arts and crafts of Tcl-Tk programming]