The procedure until is not in the core, but you can define it yourself as follows: ====== proc until {cond code} { uplevel 1 [list while !($cond) $code] } ====== See also [control]::do (in [tcllib]). [PL]: The original rewriting of the command was like this: === list while !$cond $code === but that doesn't work since a `cond` value of, say, `$i > 5` is rewritten as the condition argument `!$i > 5` which will always evaluate to false (the `!` operator has priority, and the result of evaluating it is either 1 or 0, which is never greater than 5). Other condition strings are likely to lead to other interesting errors. Rewriting the command as === list while !($cond) $code === ensures that all of `$cond` is evaluated before negating the result. ---- This doesn't implement the usual meaning of ''until'', which executes the code and then tests cond after. [Larry Smith] I use: # an unbounded loop or one with a terminating condition of while or until. # always executes at least once. If no while or until conditions is attached, # loops forever until . proc repeat {script {whenexit ""} {test ""}} { if {[catch {uplevel $script} err]} return switch -- $whenexit { "" {uplevel "while 1 \{$script\}"} "while" {uplevel "while \{$test\} \{$script\}"} "until" {uplevel "while \{!($test)\} \{$script\}"} } } The advantage of the above is you can leave out the while or until entirely and just use break to exit from anywhere in the loop. [DKF]: The usual definition is typically expressed as a do-while loop, which is a form that puts the test last. When expressed condition-first, it is natural to expect the condition to be checked first... [Larry Smith] Didn't do it that way since I use do as a compact for loop replacement (this version allows do .. by , though it still accepts x for "by"): proc do {var range loop} { set br [string first ".." $range]; set by [string first "by" $range $br+1]; if {$by == -1} {set by [string first "x" $range $br+1]} if {$by == -1} {set by 1; set end end} {set by [expr [string range $range $by+1 end]; set end [expr {$by-1}]} set from [expr [string range $range 0 $br-1]]; set to [expr [string range $range $br+2 $end]] if {$to<$from} {if {$by > 0} {! by -$by}; set cond >=} else {set cond "<="} set script "for \{set $var $from\} \{\$$var $cond $to\} \{incr $var $by\} \{$loop\}" ^^ $script } [RLH] Someone else was thinking about this too: http://christopherchase.cc/posts/tcl-until.html%|%until%|% <> Control Structure