I am trying to delete the files with . vcd extension from a tcl script. But I am getting file name too long error. I have tried puts [file delete [glob *.vcd]]
. What's the correct way to do it?
Asked
Active
Viewed 859 times
3

kabanus
- 24,623
- 6
- 41
- 74

NAVEEN PRAKASH
- 140
- 1
- 2
- 13
1 Answers
5
The problem is that
file delete [glob *.vcd]
doesn't evaluate to what you think. The glob is expanded too late, and the entire result (all your files together) are considered one single file. If you have a ton of files, that would cause that error.
Today I think you can use:
file delete {*}[glob *.vcd]
for an immediate expansion. I used to do this with eval file delete ...
if that doesn't work (old versions of TCL maybe). Also, the puts
is useless here, nothing is returned from file delete
.
There was somewhat of a discussion in the comments whether
eval file delete [glob stuff*]
is safe for weird things like files named "rm -rf ~;"
(yes, legal). The answer is yes, odd characters like ;
are escaped when returned from glob
and passed, so there is no little (never say never) worry for weird injections like that.

kabanus
- 24,623
- 6
- 41
- 74
-
You'd need `eval [linsert [glob *.vcd] 0 file delete]` in order to work. That command produces a list by inserting a two-element list `file delete` in front of the list produced by `glob *.vcd`, and then passes it to `eval`. – kostix Mar 25 '18 at 13:00
-
@kostix The second part of what you said is right, but the first I don't think so. `eval file delete [glob *.bla]` works fine for me. I'm guessing by evaluating the `glob` first, so the final command is `file delete a.bla b.bla c.bla ...` - which is OK. – kabanus Mar 25 '18 at 13:03
-
Yeah; I just have an ingrained habit of always passing `eval` a list (or list) as it essentially considers all its arguments as forming a single string—to cite the manual: «…Eval concatenates all its arguments in the same fashion as the concat command, passes the concatenated string to the Tcl interpreter recursively, and returns the result of that evaluation (or any error generated by it).». – kostix Mar 25 '18 at 13:26
-
1…It means if the name of a file expanded by `glob` contains something funny like, literally, `; rm -rf .;`, you would be `eval`-uating something like `file delete foo.txt ; rm -rf .; bar.txt` and that command would first delete `foo.txt` and then everything in the current directory, recursively (and then fail). – kostix Mar 25 '18 at 13:28
-
If you pass the `eval` command a true list (or several) its effect would be to "extract the elements" of this list (or from a single list obtained by `concat`-enation of the lists passed as argument) and evaluate the result right away—hence protecting you from any possible malicious actions by fellow users. – kostix Mar 25 '18 at 13:30
-
See also [this](https://stackoverflow.com/q/17451671/720999) for another case of a similar behaviour to be aware of—this time implemented by the `expr` command. – kostix Mar 25 '18 at 13:33
-
@PeterLewerin: Semicolons are definitely legal in filenames on OSX (just tested that) and I expect them to be legal on Linux too. Only `/` and NUL have special meanings in Unix filenames (directory separator and filename string terminator, respectively). – Donal Fellows Mar 25 '18 at 16:43
-
1`eval file delete -- [glob *.tcl]` isn't a security hole at all; the `glob` command always produces a proper list. Without the `--`, a file called `-force` might surprise you (though probably not here; it doesn't match `*.tcl`), just as it might with `file delete {*}[glob *.tcl]`… – Donal Fellows Mar 25 '18 at 16:46
-
@PeterLewerin, in POSIX filenames indeed only / and NUL are special; Donal, thank you, I stand corrected! – kostix Mar 25 '18 at 18:54
-
@PeterLewerin, OK let me declare that you a) have won, b) officially had the last word in this discussion. Thanks. As I've said, I stand corrected. I may repeat it once again if you want. ;-) – kostix Mar 25 '18 at 19:58