0

I have a directory that contains another directory named ABC_<version number>

I'd like to set my path to whatever ABC_<version number> happens to be (in a modulefile)

How do I use glob in TCL to get the name of the directory I want and put it into a TCL variable?

Thanks!

Ray Salemi
  • 5,247
  • 4
  • 30
  • 63

2 Answers2

1

The glob command expands wildcards, but produces a Tcl list of everything that matches, so you need to be a bit careful. What's more, the order of the list is “random” — it depends on the raw order of entries in the OS's directory structure, which isn't easily predicted in general — so you really need to decide what you want. Also, if you only want a single item of the list, you must use lindex (or lassign in a degenerate operation mode) to pick it out: otherwise your code will blow up when it encounters a user who puts special characters (space, or one of a small list of other ones) in a pathname. It pays to be safe from the beginning.

For example, if you want to only match a single element and error out otherwise, you should do this:

set thePaths [glob -directory $theDir -type d ABC_*]
if {[llength $thePaths] != 1} {
    error "ambiguous match for ABC_* in $theDir"
}
set theDir [lindex $thePaths 0]

If instead you want to sort by the version number and pick the (presumably) newes, you can use lsort -dictionary. That's pretty magical internally (seriously; read the docs if you want to see what it really does), but does the right thing with all sane version number schemes.

set thePaths [glob -directory $theDir -type d ABC_*]
set theSortedPaths [lsort -dictionary -decreasing $thePaths]
set theDir [lindex $theSortedPaths 0]

You could theoretically make a custom sort by the actual date on the directories, but that's more complex and can sometimes surprise when you're doing system maintenance.


Notice the use of -type d in glob. That's a type filter, which is great in this case where you're explicitly only wanting to get directory names back. The other main useful option there (in general) is -type f to get only real files.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
0

Turns out the answer was:

 set abc_path [glob -directory $env(RELDIR) ABC_*]

No need for quotes around the path. The -directory controls where you look.

Later in the modulefile

 append-path PATH $abc_path
Ray Salemi
  • 5,247
  • 4
  • 30
  • 63
  • 1
    What if that glob returns multiple directories? Do you need to `append-path PATH [join $abc_path :]`? Caveat, I don't know how module files work, so "append-path" may already do it. – glenn jackman Feb 25 '19 at 19:12