Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

WAD Bug in %@FINDFIRST function with multiple wildcards

Jul
244
6
It's clearly running the wildcards one at a time and returning the first file found with one of the wildcards, and not the first file found with all wildcards.

It's easily verifiable via the following test (see first screnshot). The order of my wildcard parameters should NOT matter.

Obviously if i'm sending a set of wildcards, I am looking for the first file out of all of them, not just the first file found in one of the [the first? the last? i didn't bother to check that deeply] wildcards sent.

BACKSTORY: I'm using this to find the first image file in a folder, and images can be one of many extensions! I've included a 2nd screenshot of how I intend to use this function. Note in my 2nd screenshot, the test would pass, but only by the coincidence of jpg being the first wildcard mentioned, and jpg being my first file. If my first file is not a jpg, using it this way fails. There's no way for me to get around this without loooping through every extension myself. It's possible, but it would be nice if TCC returned the correct value of the first file found in wildcard passed to %@FINDFIRST :)

Long story short: There is no way to find the first image file out of all possible image extensions with the %@FINDFIRST function, due to this TCC bug. Note the last two lines in this screenshot, and how the "first" result is returned incorrectly when the parameters are reversed.

1685274343722.png
1685274445962.png
 
Last edited:
I don't understand what you mean by your "first file" - are you looking for the order they're stored on the disk? Creation time? Alphabetical order? Something else?

How Windows actually returns files when given a wildcard depends on your file system. (For example, NTFS will return matching files in alphabetic order, regardless of how you originally created them.)

When you use an include list (which is what you're doing -- not precisely a wildcard search), TCC will search for files in the order you specified in the include list. It will find all of the jpg files first, then the jpeg, then the gif, then the png, etc. This is WAD.
 
If you're looking for the "first file that I created" (i.e., the oldest creation time), you cannot do that with @FINDFIRST. (Not a bug, just the way Windows works.)

However, you can do that several other ways in TCC, depending on what you want to do with the result. Both DO and FOR have a /O:d option to allow you to sort the matching files by (last modified) date. (As do COPY, MOVE, and other file handling commands.) Or you could use PDIR to create and sort the list, redirect the output to a file, and then read the first line.
 
I don't understand what you mean by your "first file" - are you looking for the order they're stored on the disk? Creation time? Alphabetical order? Something else

How perceptive. I do believe you are correct and this is a matter of misshapen intent or misunderstanding on my part.

Basically, I'm trying to do the equivalent of clicking the first image file in the folder.

The one that the "tab" would filename-complete to (assuming all images are executable at the command line, which they are on mine due to having set the appropriate environment variables)

So I guess: Alphabetical, then.

I still think, though, that swapping the parameters around shouldn't make the results different, but I guess that's a matter of opinion
 
but yea, basically I was using:

set FIRST_FILE=%@FINDFIRST[%MASK%]


And I guess, misunderstanding what FINDFIRST actually does.
 
@FINDFIRST is a wrapper for the Windows FindFirstFile API. All you're guaranteed to get back from that API is that it will be one of the files that matches the wildcard you specified.

If you want alphabetical order when you're using an include list, you'll need to use something else. Probably one of the /O:x options in the file commands that basically retrieves all matching files, then sorts them based on the /O: parameter you selected.
 
I still think, though, that swapping the parameters around shouldn't make the results different
It pretty much has to. The Windows function FindFirstFile can deal with a wildcard specification but not with multiple wildcard specifications.
Basically, I'm trying to do the equivalent of clicking the first image file in the folder.
If that's all you want, make your own function, perhaps ...

Code:
c:\users\vefatica\desktop\pics> function FIRSTFILE `%@execstr[dir /k /m /o:n /b %1$]`

c:\users\vefatica\desktop\pics> echo %@firstfile[*.png;*.jpg]
arnex4.JPG

c:\users\vefatica\desktop\pics> echo %@firstfile[*.jpg;*.png]
arnex4.JPG

You could get fully-qualified names if you need them.

Code:
c:\users\vefatica\desktop\pics> function FIRSTFILE `%@execstr[dir /k /m /o:n /f %1$]`

c:\users\vefatica\desktop\pics> echo %@firstfile[*.jpg;*.png]
C:\Users\vefatica\Desktop\Pics\arnex4.JPG
 
Thanks for the solution!

I made it file-specific (/a:-d), tried it, and found something interesting....
It doesn't seem to work with files with % in the name. I guess that's not surprising. I hate those files.

1685407640316.png



My personal solution was sooooooooooooooooooooooooooooooooooooooooooooooooooooo much more verbose haha.




Code:
@Echo OFF
REM USAGE: $0 {filemask to seach for first file from}

set VERBOSITY=1 %+ REM 0=silent, 1=announce conclusions, 2=announce some debug, 3=announce every filename

REM Get file mask
    set MASK=*.*
    if "%1" ne "" (set MASK=%1)
    if %VERBOSITY% GE 2 (%COLOR_IMPORTANT_LESS% %+ echo * MASK set to: %MASK%)

REM Find "first" file:
    REM This was not valid because FINDFIRST only finds the first file matching in your list, 
    REM not the first file on the harddrive out of all the files sent to FINDFIRST
    REM         set FIRST_FILE=%@FINDFIRST[%MASK%]

    set FIRST_FILE=
    for /h /o:n %filename in (%MASK%) do (
        if %VERBOSITY% GE 3 (%COLOR_IMPORTANT% %+ echo * Checking file: %filename)
        if %SUBSTR[%%,%filename] != 0 (
            if %VERBOSITY% GE 2 (
                %COLOR_WARNING% 
                echo WARNING: filename=%filename% has percent - this script will probably fail %+ %COLOR_NORMAL%
                echo set escaped_filename=%@REPLACE[%%,%%%%,%filename]
                set      escaped_filename=%@REPLACE[%%,%%%%,%filename]
                echo     escaped_filename=%escaped_filename%
            )
        )
        set firstFile=%filename%
        set FIRST_FILE=%filename%
        goto :Got_It
    )
    :Got_It
    if %VERBOSITY% GE 1 (%COLOR_IMPORTANT% %+ echo * FIRST_FILE set to: %FIRST_FILE%)


Mine doesn't work for files with percent either...

1685407788506.png
 

Similar threads

Back
Top