Version 3 of Unixy minitools

Updated 2007-08-28 08:49:59 by suchenwi

Richard Suchenwirth 2006-01-31 - The idea that two-letter commands are easier for the user was actually also present in Multics, but Unix popularized them to a much wider audience. Especially stylus-tapping on a PocketPC, rm is just more convenient that file delete.

The following set of procs and aliases all have well-known names, but don't expect the full features of their Unix counterparts - they're just "unixy", but pretty helpful already. Though I use them in Sepp, there's almost no dependencies either way (see at bottom). Feel free to use them, or to add more :^)

#-- This is just a bait for auto_index, because aliases aren't included there...

 proc unix {} {return "unixy toolset 0.1 loaded"}

 proc alias args {
   # Set an alias: alias foo = bar grill
   switch [llength $args] {
      0 {join [map docstring [interp aliases]] \n}
      1 {docstring $args}
      default {
         foreach {name eq} $args break
         if {$eq ne "="} {error [docstring alias]}
         eval [list interp alias {} $name {}] [lrange $args 2 end]
 alias ? = set ::errorInfo
 proc  -f name {expr {[file exists $name] && [file type $name] eq "file"}}
 alias -r  =  file readable
 alias -w  =  file writable
 alias -x  =  file executable
 alias -z  =  string eq ""

 proc  at {time body} {
   set dt [expr {[clock scan $time]-[clock sec]}]
   if {$dt<0} {incr dt 86400}
   after [expr {$dt*1000}] $body
 proc cat files {
    set res ""
    foreach file [eval glob $files] {
        set fp [open $file]
        append res [read $fp]
        close $fp
    set res
 alias cp = file copy -force
 proc  du {{directory .}} {
    set res 0
    foreach item [glob -nocomplain $directory/*] {
        switch -- [file type $item] {
            directory {incr res [du $item]}
            file {
                set res [expr {$res+([file size $item]+0)/1024}]
    set res
 proc date {{x ""}} {
     if {$x eq ""} {set x [clock seconds]}
     clock format $x -format %Y-%m-%d,%H:%M:%S
 proc echo {string {redirector -} {file -}} {
    set postcmd {close $fp}
    switch -- $redirector {
        >       {set fp [open $file w]}
        >>      {set fp [open $file a]}
        default {set fp stdout; set postcmd ""}
    puts $fp $string
    eval $postcmd
 proc  grep {re args} {
   foreach file [eval glob $args] {
        set fp [open $file]
        set n 0
        while {[gets $fp line] >=0} {
            incr n
            if [regexp $re $line] {puts "$file:$n $line"}
        close $fp
 proc  ll  args {
   if ![llength $args] {set args [glob *]}
   set res {}
   foreach f [lsort $args] {
      lappend res "[date [file mtime $f]]  [format %6d [file size $f]]  $f"
   join $res \n
 proc  ls  {{x .}} {lsort [glob -nocom -dir $x *]}
 alias mv = file rename
 alias rm = file delete
 proc  touch file {close [open $file a]}
 proc  wc file {
   # number of lines, words, characters in file
   set l 0; set w 0; set c 0
   set f [open $file]
   while {[gets $f line]>=0} {
      incr l
      incr w [llength [split $line]]
      incr c [string length $line]; incr c
   close $f
   list $l $w $c
 proc wc-l file {lindex [wc $file] 0}

#------------------- name=value assignment

 proc know what {proc unknown args $what\n[info body unknown]}

 know {if [regexp (.+)=(.+) [lindex $args 0] -> left right] {
          return [uplevel 1 [list set $left [lreplace $args 0 0 $right]]]

In alias, docstring is used, and map, which uses this simple implementation:

 proc map {f list} {
   set res {}
   foreach el $list {lappend res [$f $el]}
   set res

See also Playing Bourne shell

Category Development | Category File | Arts and crafts of Tcl-Tk programming