Welcome, Guest |
TOPIC:
find files pitfall 23 Sep 2021 18:42 #19685
|
Guys, In the German Xbase++ forum there´s been a discussion about the Directory() behaviour with the search pattern "862*.jpg". www.xbaseforum.de/viewtopic.php?p=139600#p139600 The problem can be reproduced with these two (long name ! ) files: 86220200630.JPG 86720210702.JPG Because of the search pattern, only this file should be found. 86220200630.JPG but both files are found ! Since VO and X# give the same result I took a closer look. The problem occurs when long filename are used and the DOS 8.3 names feature is enabled on the search drive. You can check the current state of your drives when you open a CMD box with admin rights and run the fsutil.exe. fsutil 8dot3name query <Drive:> These are the results of my "C:" and "D:" drives 8dot3 name creation is enabled on C: 8dot3 name creation is disabled on D: When i search in my C:\Test dir both files are found and only the search in my D:\test directory shows one file. The problem is that in the C:\Test dir a comparison takes place with the short filenames and the long filenames. If the pattern is found in the short filename it is interpreted as a hit. That´s the content of my C:\Test dir. As you can see both short file names start with "862" C:\Test>dir/X 862*.jpg
Volume in Laufwerk C: hat keine Bezeichnung.
Volumeseriennummer: DA00-F3C0
Verzeichnis von C:\Test
23.09.2021 18:00 5 862202~1.JPG 86220200630.JPG
23.09.2021 18:00 5 8624E7~1.JPG 86720210702.JPG
2 Datei(en), 10 Bytes
0 Verzeichnis(se), 119.755.788.288 Bytes frei the search works in my D:\test dir. It seems the only way to fix this behaviour is to disable the 8dot3name feature, or to implement a own pattern search ? That's my test code: FUNCTION SearchFiles()
LOCAL aFiles, aDir AS ARRAY
LOCAL i AS DWORD
LOCAL hFile, hFind AS PTR
LOCAL cDir, cFile AS STRING
LOCAL struFindData IS _winWIN32_FIND_DATA
cDir := "c:\Test\"
// cDir := "d:\Test\"
aFiles := {}
// long filenames
AAdd(aFiles,"86220200630.JPG")
AAdd(aFiles,"86720210702.JPG")
FOR i := 1 TO ALen(aFiles)
IF ! File( cDir + aFiles [i])
IF ( hFile := FCreate( cDir + aFiles[i], FC_NORMAL ) ) != F_ERROR
FWrite( hFile, "Jimmy" )
FClose( hFile )
ENDIF
ENDIF
NEXT
aDir := Directory( cDir + "862*.JPG")
?
? "Directory() results"
?
FOR i := 1 UPTO ALen ( ADir )
? aDir [ i , F_NAME ]
NEXT
?
? "FindxxxFile results"
?
cFile := cDir + "862*.JPG"
IF ( hFind := FindFirstFile( String2Psz ( cFile ) , @struFindData) ) != INVALID_HANDLE_VALUE
// note: Psz2String ( @struFindData.cAlternateFileName ) shows the 8.3 filename if any
? Psz2String ( @struFindData.cFileName ) , Psz2String ( @struFindData.cAlternateFileName )
WHILE FindNextFile(hFind, @struFindData)
? Psz2String ( @struFindData.cFileName ) , Psz2String ( @struFindData.cAlternateFileName )
ENDDO
FindClose ( hFind )
ENDIF
#ifdef __XSHARP__
?
? "System.IO.Directory.GetFiles results"
?
VAR files := System.IO.Directory.GetFiles(cDir, "862*.JPG" )
FOREACH VAR f IN files
? System.IO.Path.GetFileName ( f )
NEXT
#endif
RETURN TRUE regards Karl-Heinz |
Please Log in or Create an account to join the conversation. |
find files pitfall 23 Sep 2021 22:42 #19690
|
Karl-Heinz, Maybe the Directory function should (internally) double check to see if the found file matches the mask? We have a _Like() function that could be used for that. Robert XSharp Development Team The Netherlands |
Please Log in or Create an account to join the conversation. |
find files pitfall 24 Sep 2021 13:28 #19701
|
Hello Robert, Karl-Heinz, Reading this amazed me. What is the use of DOS 8.3 filenames anyway? If not already disabled, I think every sensible system administrator should do that (I think it's fsutil behavior set disable8dot3 3, correct?) If 86720210702.JPG becomes 8624E7~1.JPG , a totally random name change, then you could expect to find anything. This of course again comes from Microsoft. Logically this file should be called 867202~1.jpg I'd say. I often like older techniques to remain available but who wants to see a >8+3 filename converted in 2021 to a 8+3 file name which was from before 1994? Dick |
Please Log in or Create an account to join the conversation. |
find files pitfall 03 Oct 2021 12:37 #19814
|
Guys, the advice of Robert to use the _Like() function seems the way to go. Here´s a modified test function: FUNCTION SearchFiles2()
LOCAL cDir, sWildCard AS STRING
LOCAL aFiles AS ARRAY
LOCAL files AS STRING[]
LOCAL i AS DWORD
LOCAL hFile AS PTR
cDir := "c:\Test\" // 8dot3name enabled
// cDir := "d:\Test\"
aFiles := {}
AAdd(aFiles,"86220200630.JPG")
AAdd(aFiles,"86720210702.JPG")
AAdd(aFiles,"86220200630.Txt")
AAdd(aFiles,"86720210702.Txt")
AAdd(aFiles,"Test1.htm")
AAdd(aFiles,"Test1.html")
AAdd(aFiles,"TEst2.html")
// sWildCard := "*.???"
// sWildCard := "*.*"
sWildCard := "862*.jpg"
// sWildCard := "86220200630.JPG"
// sWildCard := "862*.txt"
// sWildCard := "*.h*"
// sWildCard := "*.htm"
// sWildCard := "*.html"
? "Current search mask: " + sWildCard
FOR i := 1 TO ALen(aFiles)
IF ! File( cDir + aFiles [i])
IF ( hFile := FCreate( cDir + aFiles[i], FC_NORMAL ) ) != F_ERROR
FWrite( hFile, "Jimmy" )
FClose( hFile )
ENDIF
ENDIF
NEXT
?
? "System.IO.Directory.GetFiles results"
?
files := System.IO.Directory.GetFiles(cDir, sWildCard )
FOREACH cFile AS STRING IN files
VAR oFile := System.IO.FileInfo{cFile}
? _Like ( sWildCard:ToUpper() , oFile:Name:ToUpper() ) , oFile:Name
/*
Only if _Like() returns true, the file should be added inside
the Directory() function.
*/
NEXT
?
? PathMatchSpec ( "Test.htm" , "*.htm" ) // ok, true
? PathMatchSpec ( "Test.html" , "*.htm" ) // ok, false
? PathMatchSpec ( "Test.html" , "*.html" ) // ok, true
RETURN TRUE
[DllImport("shlwapi.dll", CharSet := CharSet.Auto)] ;
FUNCTION PathMatchSpec( pszFileParam AS STRING , pszSpec AS STRING ) AS LOGIC A side effect is that a search with a pattern like "*.htm" no longer includes "*.html" files. Just activate the line sWildCard := "*.htm" and you´ll see that the - imo correct - results are now: .T. Test1.htm .F. Test1.html .F. TEst2.html BTW I. Another option to filter out files according the file extension is to use the API function PathMatchSpec() - see the PathMatchSpec() samples. BTW II. Without looking directly at the created short file names you´ll never know how such names look like. Simply use the pattern "862*.txt" instead of "862*.jpg" and you´ll see that now only the file "86220200630.Txt" will be found ... regards Karl-Heinz |
Please Log in or Create an account to join the conversation. Last edit: by Karl-Heinz. |
find files pitfall 05 Oct 2021 08:29 #19829
|
Karl Heinz, I will add the check to the runtime. Btw if you use Like() instead of _Like() then you do not have to uppercase the strings in your code. Like() is case insensitive. Robert XSharp Development Team The Netherlands |
Please Log in or Create an account to join the conversation. |
find files pitfall 06 Oct 2021 18:17 #19849
|
Robert, my intention to use _Like() instead of Like() was that Like() behaves differently when the Fox dialect is used. FUNCTION Like(sWildCard AS STRING, sSource AS STRING) AS LOGIC
IF XSharp.RuntimeState.Dialect == XSharpDialect.FoxPro
RETURN _Like(sWildCard, sSource)
ENDIF
RETURN _Like(Upper(sWildCard), Upper(sSource)) @all When I look at the result of the X#/VO Directory() function, i see that the content of the array returned has been expanded. The new array constants are marked with // new CONST EXPORT F_NAME := 1 AS INT
CONST EXPORT F_SIZE := 2 AS INT
CONST EXPORT F_DATE := 3 AS INT
CONST EXPORT F_WRITE_DATE := 3 AS INT // New
CONST EXPORT F_TIME := 4 AS INT
CONST EXPORT F_WRITE_TIME := 4 AS INT // New
CONST EXPORT F_ATTR := 5 AS INT
CONST EXPORT F_EA_SIZE := 6 AS INT // New:
CONST EXPORT F_CREATION_DATE := 7 AS INT // New
CONST EXPORT F_CREATION_TIME := 8 AS INT // New
CONST EXPORT F_ACCESS_DATE := 9 AS INT // New
CONST EXPORT F_ACCESS_TIME := 10 AS INT // New Now, showing a X#/VO Directory() result like ? ShowArray ( aDirectoryResult ) a[1] = {[0000000010]0x0141B42A} (A)
a[1][1] = 86220200630.Txt (C)
a[1][2] = 5 (N)
a[1][3] = 29.09.2021 (D)
a[1][4] = 08:30:11 (C)
a[1][5] = A (C)
a[1][6] = 32 (N)
a[1][7] = 27.09.2021 (D)
a[1][8] = 07:39:26 (C)
a[1][9] = 29.09.2021 (D)
a[1][10] = 08:30:11 (C) regards Karl-Heinz |
Please Log in or Create an account to join the conversation. |