Page 1 of 1

ExamineDirectory()

Posted: Mon Feb 15, 2016 2:42 pm
by IdeasVacuum
What is the Windows API equivalent to PB's ExamineDirectory()?

Re: ExamineDirectory()

Posted: Mon Feb 15, 2016 2:57 pm
by Michael Vogel
FindFirstFile, I believe...

Code: Select all

Path.s = "C:\Windows\"
Name.s = Path + "w*.*"
SearchHandle = FindFirstFile_(Name, Info.WIN32_FIND_DATA)
If SearchHandle <> #INVALID_HANDLE_VALUE
	Repeat
		Entry.s = PeekS(@Info\cFileName[0])
		If Info\dwFileAttributes&#FILE_ATTRIBUTE_DIRECTORY=#Null
			Debug Entry
		EndIf
	Until FindNextFile_(SearchHandle,Info) = #False
	FindClose_(SearchHandle)
EndIf

Re: ExamineDirectory()

Posted: Mon Feb 15, 2016 4:20 pm
by IdeasVacuum
Excellent, thank you Michael 8)

Re: ExamineDirectory()

Posted: Sun Jan 14, 2018 4:21 am
by Dude
Nice code, Michael... but can this work recursively if we just use a root path instead?

Re: ExamineDirectory()

Posted: Fri Jun 29, 2018 9:20 am
by Pierre Bellisle
Here is one way. It is doing subfolders.
I avoided a recursive procedure because code execution will slow down as folder count grows.
A while/Wend is faster.

Depending on the wanted result, one can look at "localized filename", "symbolic link (aka soft link)", "hard link", junction, "Wow64 File system redirection", "short and long filename".

Code: Select all

EnableExplicit

If OpenConsole()
  Dim sSubFolder.s(0)             ;Array of subfolder names
  Define.s sFolder                ;Folder
  Define.s sFile                  ;File
  Define.s sFilter                ;Filespec WildCard 
  Define.i FileCount              ;Total files found
  Define.i FolderCount            ;Total folders found
  Define.i SubFolderLevel         ;Subfolder level index
  Define.i hFile                  ;Find file handle
  Define.WIN32_FIND_DATA FileData ;Find file handle  
  
  sFolder = "C:\Windows\Boot\" ;Need an ending backslash
  sFilter = "*.*"              ;Filespec WildCard for files only, folders are intentionally excluded
  
  While #True
    hFile = FindFirstFile_(sFolder + "*", FileData) ;Get all files and folders including "." and ".."
    If hFile <> #INVALID_HANDLE_VALUE ;Make sure we have a valid handle
      Repeat ;Get everything
        sFile = PeekS(@FileData\cFileName[0]) ;Copy data to a string
        If FileData\dwFileAttributes & #FILE_ATTRIBUTE_DIRECTORY ;If it's a folder
          If sFile <> "." And sFile <> ".." ;Check For "." And "..", only those can end With a dot.
            FolderCount = FolderCount + 1 ;Increment folder count
            SubFolderLevel = SubFolderLevel + 1 ;Increment sub folder index
            ReDim sSubFolder(SubFolderLevel) ;Make room to store it
            sSubFolder(SubFolderLevel) = sFolder + sFile + "\" ;Put sub folder name in array
            ConsoleColor(6, 0)
            PrintN("Folder: " + sSubFolder(SubFolderLevel) + sFile) ;Show subfolder name   
            ConsoleColor(7, 0)  
          EndIf    
        Else ;It's a file
          If PathMatchSpec_(sFile, sFilter) ;Get file according to sFilter filespec via PathMatchSpec API
            PrintN("File:   " + sSubFolder(SubFolderLevel) + sFile) ;Show file name 
            FileCount = FileCount + 1 ;Increment file count
          EndIf              
        EndIf  
      Until FindNextFile_(hFile,FileData) = #False ;Do as long as there is data
      FindClose_(hFile) ;Clean up this handle
    EndIf
    If SubFolderLevel = 0 ;All sublevel are done
      Break               ;So exit
    EndIf  
    sFolder = sSubFolder(SubFolderLevel) ;Point to a new subfolder
    SubFolderLevel = SubFolderLevel - 1  ;Going up one level
  Wend
  ConsoleColor(14, 0)
  PrintN("Foldercount: " + Str(Foldercount)) 
  PrintN("Filecount:   " + Str(FileCount))
  ConsoleColor(7, 0)
  
  FindClose_(hFile)

  Input()
  CloseConsole()
     
EndIf

Re: ExamineDirectory()

Posted: Wed May 01, 2024 12:54 pm
by BarryG
Just trying Michael's snippet today but the results are NOT case-sensitive:

Code: Select all

Path.s = "C:\Windows\"
Name.s = Path + "t?unk*" ; Lower-case "t" only wanted.
SearchHandle = FindFirstFile_(Name, Info.WIN32_FIND_DATA)
If SearchHandle <> #INVALID_HANDLE_VALUE
	Repeat
		Entry.s = PeekS(@Info\cFileName[0])
		If Info\dwFileAttributes&#FILE_ATTRIBUTE_DIRECTORY=#Null
			Debug Entry ; Shows "Twunk_16.exe" and "Twunk_32.exe" :(
		EndIf
	Until FindNextFile_(SearchHandle,Info) = #False
	FindClose_(SearchHandle)
EndIf
How would I make it case-sensitive? Thanks.

Re: ExamineDirectory()

Posted: Wed May 01, 2024 7:24 pm
by Michael Vogel
Didn't play around with FindFirstFileEx but it may have an option FIND_FIRST_EX_CASE_SENSITIVE.
Anyhow using the PB internal commands will allow to do this much easier.

Re: ExamineDirectory()

Posted: Wed May 01, 2024 10:27 pm
by BarryG
I found a StackOverflow post about FIND_FIRST_EX_CASE_SENSITIVE but apparently that doesn't work, and the only way for a case-sensitive match is to edit the Registry before searching. Don't really want to do that to my customers' PCs. Hmm.

Re: ExamineDirectory()

Posted: Wed May 01, 2024 10:42 pm
by Fred
The file system is case insensitive, why do you need a case sensitive search ?

Re: ExamineDirectory()

Posted: Wed May 01, 2024 11:05 pm
by BarryG
For file renaming when matching specific files. So I can rename "FilesLikeThis.TXT" to "FilesLikeThis.txt" as one example. Can't do that with a wildcard search of "*.TXT" because it won't match just ".TXT" alone; it'll return all files with that extension and give me a false report of how many actual matching files there were.

Another example would be per my snippet above, where I want to find "twunk_16.exe" but not "Twunk_16.exe" with a wildcard of "t?unk*".

Re: ExamineDirectory()

Posted: Thu May 02, 2024 4:39 am
by AZJIO
BarryG
https://www.purebasic.fr/english/viewto ... 94#p597194

3 - regular expression
(?-i).+?\.TXT
(?-i)\A.+?\.TXT\z

2 - listing file extensions (but this still works as a bug that I will fix for Windows)
TXT
no longer works, I replaced it

Code: Select all

If CompareMemoryString(@tmp$, PeekI(@Ext()), #PB_String_NoCase) = #PB_String_Equal
;If tmp$ = Ext()
Now I need to add a new "CaseSensitive" parameter to the function to make it more flexible.