Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Globbing files with tilde

101 views
Skip to first unread message

Luc

unread,
Dec 10, 2022, 11:06:27 PM12/10/22
to
I rewrote my very old file system scanning code, which had been written
for Windows. When I migrated to Linux (looong time ago), I adopted
the `find' command.

The only problem I seem to have with it is that it won't find files
that begin with a tilde. I want them. I want ALL files.

Upon googling, I understand that [glob] likes to assume that the tilde
more often than not means the user's home directory. And I found this
thorough explanation by the illustrious Donal Fellows:

https://stackoverflow.com/questions/12152929/turn-off-tilde-substitution-in-filenames

Donal says:

"The simplest way to stop a leading ~ from being a problem is to put
./ in front of it, and to always use the -directory option to glob."

Well, my first version of the code was doing a [cd] before globbing
every directory so I changed that to always use the -directory option,
but that didn't solve the problem. Now I'm stumped and beg for your
help once again. The damndest thing is that the exact same [glob] line
works fine in Tkcon.

Here is my code:


set ::FILELIST {}
proc p.scan {path} {

;# SCAN FILES AND DIRECTORIES, HIDDEN OR NOT
set _ftypes {b c d f l p s hidden}

foreach type $_ftypes {
foreach _file [glob -nocomplain -tails -types $type -directory $path *] {

if {$_file == "."} {continue}
if {$_file == ".."} {continue}

set _filepath [file join $path $_file]

;# ADD FILE TO FILELIST
if {[file isfile $_filepath]} {
lappend ::FILELIST $_filepath
} else {
;# THIS LINE FOR DEBUGGING ONLY
if {! [file isdirectory $_filepath]} {puts $_filepath}
}

;# IF IT IS A DIRECTORY, GO INTO IT AND REPEAT PROCEDURE
if {[file isdirectory $_filepath] && [file type $_filepath] != "link"} {
p.scan $_filepath
cd ..
}
}
}
}


--
Luc
>>

Rich

unread,
Dec 11, 2022, 12:58:42 AM12/11/22
to
Luc <n...@no.no> wrote:
> The only problem I seem to have with it is that it won't find files
> that begin with a tilde. I want them. I want ALL files.

Which 'it' do you mean, the GNU 'find' command, or TCL's 'glob'?

And for me, both seem to find files with tilde's just fine:

Test directory contents:

$ ls -1
end~
mid~dle
~begin

GNU find inside the test directory:

$ find -type f
./~begin
./mid~dle
./end~

TCL's glob inside the same test directory:

$ rlwrap tclsh
% join [glob *] \n
~begin
mid~dle
end~
%

Both found files with tilde's at the beginning, in the middle, and at
the end.

Christian Gollwitzer

unread,
Dec 11, 2022, 2:20:17 AM12/11/22
to
Am 11.12.22 um 05:06 schrieb Luc:
> I rewrote my very old file system scanning code, which had been written
> for Windows. When I migrated to Linux (looong time ago), I adopted
> the `find' command.
>
> The only problem I seem to have with it is that it won't find files
> that begin with a tilde. I want them. I want ALL files.
>
> Upon googling, I understand that [glob] likes to assume that the tilde
> more often than not means the user's home directory.


It is worse than that: ALL commands working on files expand the leading
tilde into home directories. Thankfully, this misfeature will be removed
in Tcl9 https://core.tcl-lang.org/tips/doc/trunk/tip/602.md

But "glob" returns the ~files unmodified, therefore this does not work:

foreach fn [glob *] {
lappend fds [open $fn]
}

Here, a ~file in the current directory will lead "open" to fail.


> foreach _file [glob -nocomplain -tails -types $type -directory $path *] {
>
> if {$_file == "."} {continue}
> if {$_file == ".."} {continue}
>
> set _filepath [file join $path $_file]
>
> ;# ADD FILE TO FILELIST
> if {[file isfile $_filepath]}

I think that the bug is in here. "file isfile" and "file join" fail due
to the ~problem:

(kbskit) 50 % file join /temp ~test
~test

You need to do:

(kbskit) 51 % file join /temp ./~test
/temp/~test

But beware that this is not always what you want to do: In case the
second part really is an absolute path (can't happen in your case now),
you don't want the prefix:


(kbskit) 55 % file join /temp /test
/test
(kbskit) 56 % file join /temp .//test
/temp/./test

Christian
0 new messages