Tcl 8.3 introduces some new options to glob which generally make scripts more robust and cross-platform. For example, they help to avoid incorrect usage like:
glob $dir/* glob [file join $dir *]
which both fail if $dir contains glob sensitive characters. The new syntax would be:
glob -dir $dir *
which besides fixing the above problem has the added benefit of working on MacOS, since '/' is not assumed to be the directory separator.
If you want to write code using the new glob flags/options, such as glob -dir $dir -type d *, obviously your new code will no longer work with older versions of Tcl (e.g. 8.0-8.2). If you would like a compatibility layer which can be loaded into Tcl 8.0-8.2 (probably even older versions of Tcl too), overriding the old glob to emulate the new one in Tcl 8.3, here it is:
if {[info tclversion] < 8.3} { ;proc getOpts {{take_value ""} {set "set"}} { upvar args a upvar opts o while {[string match \-* [set arg [lindex $a 0]]]} { set a [lreplace $a 0 0] if {$arg == "--"} { return } else { if {[set idx [lsearch -regexp $take_value \ "^-?[string range $arg 1 end]( .*)?$"]] == -1} { set o($arg) 1 } else { if {[llength [set the_arg \ [lindex $take_value $idx]]] == 1} { $set o($arg) [lindex $a 0] set a [lreplace $a 0 0] } else { set numargs [expr {[lindex $the_arg 1] -1}] $set o($arg) [lrange $a 0 $numargs] set a [lreplace $a 0 $numargs] } } } } } rename glob __glob ;proc glob {args} { getOpts {-t -types -type -dir -path} # place platform specific file separator in variable 'separator's regexp {Z(.)Z} [file join Z Z] "" separator if {[info exists opts(-join)]} { unset opts(-join) set args [list [eval file join $args]] } set add "" foreach t {type types} { if {[info exists opts(-$t)]} { eval lappend opts(-t) $opts(-$t) unset opts(-$t) } } if {[info exists opts(-t)]} { if {[set item [lsearch -exact $opts(-t) "d"]] != -1} { set opts(-t) [lreplace $opts(-t) $item $item] set add $separator set isdir 1 } } if {[set nocomplain [info exists opts(-nocomplain)]]} { unset opts(-nocomplain) } if {[info exists opts(-path)]} { if {[info exists opts(-dir)]} { if {$nocomplain} { return "" } else { error "Can't use option '-dir' with '-path'" } } regsub -all {[][*?\{\}\\]} $opts(-path) {\\&} prefix unset opts(-path) } elseif {[info exists opts(-dir)]} { regsub -all {[][*?\{\}\\]} $opts(-dir) {\\&} prefix append prefix ${separator} unset opts(-dir) } else { set prefix "" } set res {} foreach arg $args { eval lappend res [__glob -nocomplain -- \ "${prefix}${arg}${add}"] } if {[info exists opts(-t)]} { # we ignore arguments to -t which haven't yet been handled, # since they are assumed to be platform specific unset opts(-t) } if {[set llen [llength [array names opts]]]} { set ok "-nocomplain, -join, -dir <dir>,\ -path <path>, -types <list of types>" if {$llen > 1} { error "bad switches \"[array names opts]\":\ must be $ok or --" } else { error "bad switch \"[array names opts]\":\ must be $ok or --" } } elseif {[llength $res]} { if {[info exists isdir]} { foreach r $res { lappend newres [string trimright $r $separator] } return $newres } else { return $res } } elseif {$nocomplain} { return "" } else { switch -- [llength $args] { 0 { error "wrong # args: should be \"glob ?switches?\ name ?name ...?\"" } 1 { error "no files matched glob pattern \"$args\"" } default { error "no files matched glob patterns \"$args\"" } } } } }
--
I'm confused. Can you show some old code that breaks?
By the way, I assume you meant to say "if you want your OLD glob code to work ..."
Vince: hopefully the clarification above solves your confusion. The Tcl 8.3 changes to glob are 100% backwards compatible. The goal of this page is to provide forwards compatibility for people who write 'modern' code but still want those stuck at Tcl 8.0-8.2 to be able to use it. It handles most common uses of Tcl 8.3's glob.
This approach deserves its own page IMO: Forward compatibility --jcw