[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 replace /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'', for which we first create a shorter version: proc alias {new args} {eval [list interp alias {} $new {}] $args} alias echo puts stdout alias read gets stdin ;# if we don't need the real [read] alias cp file copy -force alias rm file delete alias mkdir file mkdir # alias whoami subst $::tcl_platform(user) # raises cryptic error message when called with args, hence: proc whoami {} {set ::tcl_platform(user)} alias -r file readable alias -w file writable 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...) ---- 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"}} proc -z string {expr {[string length $string]==0}} 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 ::[incr n] $i} 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; puts [eval ! $args]} This wraps the required [clock] calls into a lookalike of UNIX's ''date'' command: proc date {args} { set cmd {clock format [clock sec]} foreach arg $args { if {$arg=="-u"} { append cmd " -gmt 1" } elseif [regexp {\+(.+)} $arg -> fmt] { append cmd " -format [list $fmt]" } else {error "usage: date ?-u? ?+%H%M%S...?"} } eval $cmd } To tell the truth, this is not a Bourne shell issue, but in sh scripts, system executables are often called which may not be present (or with different behavior) on other platforms. proc : args {set ::? 0} ;# sh's no-op - but resets exit code For the path-sensitive . in sh see [source]. ---- [Tcl and other languages] - [Arts and crafts of Tcl-Tk programming]