Thursday, January 27, 2011

Filename Expansion in Tcl

Stupid, stupid, Tcl. If you want to run a shell command with a glob filename, like *.h, you can't just do:
exec ls -l *.h

You have to explicitly tell Tcl to expand the glob, because it will pass *.h to the shell literally. But you also can't do:
exec ls -l [glob *.h]

because it will pass the entire list to the shell literally (thanks, Tcl, that's useful). You get lucky and it works if there is exactly one file matched by the glob. Otherwise ls will complain that there's no file called "a.h b.h c.h".

So what do you do? Unfortunately, if you pull up the man page for exec on the internet, it tells you a way to do this that is only syntactically valid for Tcl 8.5 or greater. For those of us living in the past, the demonic incantation you must utter is:
eval [list exec ls -l] [glob *.h]

Don't use Tcl unless you have to.

3 comments:

Anonymous said...

You can also do


foreach f [glob *.h] {
exec ls -l $f
}

Bill Night said...

Yeah, that's OK. But if you need to pass all the files in a single command (for instance for ls -lrt, to sort with newest last), it doesn't help. Even with ls -l, the glob results are not in alphabetical order (in 8.4 at least), so your solution does something slightly different.

Anonymous said...

An old post in a series of even older posts, but just wanted to stop by and thank you for cheering me up a bit about having to use Tcl - I'm glad to know I'm not the only one going through this pain.

It's like a completely retarded Lisp.