Luc <
[email protected]d> wrote:
Thank you again. Your code of course works.
Then a new problem comes up. Right after that code, this:
set ::FILELIST [join [lsort -dictionary $::FILELIST] "\n"]
error:
list element in quotes followed by "," instead of space
while executing
"lsort -dictionary $::FILELIST"
(procedure "p.5.run" line 15)
invoked from within
"p.5.run"
(file "/home/tcl/bin/dirlist-nix.tcl" line 188)
The content is obviously the entire list of (almost) all files in my
hard disk. It is not formatted data or even completely predictable data.
Am I supposed to "escape" anything to make this work?
No, you are supposed to handle it with a wee bit of knowledge of how
Tcl's going to interpret it.
OK. I'm going to try this:
set ::FILELIST [join [lsort -dictionary [list $::FILELIST]] "\n"]
It works. OK. But I'm not sure why.
Because you created a list, containing a single element, that single
element being the entire string you got back from your exec call.
Why do I have to explicitly tell Tcl that $::FILELIST is a list
You did not tell Tcl it was a list.
, or rather, why do I have to convert it into a list?
Because lsort works on lists and only lists. If you pass it a string
(which is what you are doing), Tcl will make an attempt to convert the
string to a list. But, if the string is not properly formatted (i.e.,
certian delimiter characters not properly escaped) that attempt to
convert to a list will fail, with the error message you got.
This is why I keep cautioning you to: *do not use list operators on
strings*. This is the error you get when you do that, except you don't
always get it. Sometimes it stays hidden for years, until one day, a
string with an unescaped delimiter passes through the code, and then,
*boom* things blow up.
I always assumed that Tcl shimmied automatically as needed.
It does, but it makes assumptions on how the string being shimmered is formatted, if the string violates those assumptions, then you get this
error message.
Apparently, I've been wrong.
Yep.
Now, for your fix, there's three possible fixes. One, if you know for
sure you will never have a newline in a filename (Linux allows
filenames to contain newlines -- but usually one has to go out of one's
way to create one) then you need to *convert* the *string* you receive
from [exec] into a list, *before* you try to sort it.
You convert it to a string using [split]. You'd need to first:
[split $::FILELIST \n]
to break the string in ::FILELIST into a proper list, using \n as the delimiter. Then lsort will sort the resulting, proper list, just fine.
Now, if you want to be absolutely sure you never have problems when
exec'ing 'find' to obtain filenames, you want to replace your "-print"
with "-print0" which instructs find to output ASCII null's between each
file instead of newlines. ASCII null is one of the very few characters
that cannot be used in a Linux filename, so it can never occur in the
data you receive from find.
Then, immedately after receiving the giant string back from find in the
exec call, convert it to a proper list using split, only use \0 as the delimiter instead of \n:
set ::FILELIST [split $::FILELIST \0]
I did a quick test here using 8.6.12 on Linux and the ASCII null's
arrive from the [exec] call and therefore can be used as the delimiter
for [split].
The third fix is you switch to using Tcllib's fileutil module,
specifically its ::fileutil::find call, creating your own 'filtercmd'
to remove from what is found those directory trees you don't want to do anything with.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)