• Globbing files with tilde

    From Luc@21:1/5 to All on Sun Dec 11 01:06:22 2022
    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


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Sun Dec 11 05:58:38 2022
    Luc <[email protected]> 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Sun Dec 11 08:20:11 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)