robertjohns 0 Posted May 29, 2023 14 minutes ago, KodeZwerg said: Please compare with my approach, I posted earlier a full demo app that works straight out of the box, would like to see time results and if my way would also benefit of a full exclusion from giving names. Thanks but it still search the windows directory even after Exclusion Share this post Link to post
dummzeuch 1505 Posted May 29, 2023 31 minutes ago, robertjohns said: Thanks but it still search the windows directory even after Exclusios You should specify the complete path to exclude: C:\Windows Not just Windows Share this post Link to post
robertjohns 0 Posted May 29, 2023 44 minutes ago, dummzeuch said: You should specify the complete path to exclude: C:\Windows Not just Windows Same result not excludes Share this post Link to post
KodeZwerg 54 Posted May 29, 2023 function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var tmp, Folders, Files: TFindArray; splitIncluded, splitExcluded: TFindArray; i, ii: Integer; begin SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); if (Length(AFoldersMustExist) > 0) then begin if (0 <> Pos(';', AFoldersMustExist)) then splitIncluded := AFoldersMustExist.Split([';']) else AddStrArr(splitIncluded, AFoldersMustExist); end; if (Length(AExludedFolders) > 0) then begin if (0 <> Pos(';', AExludedFolders)) then splitExcluded := AExludedFolders.Split([';']) else AddStrArr(splitExcluded, AExludedFolders); end; // collect folder(s) to work on if AIncludeSubFolders then tmp := FindExFolders(ABasePath, AIncludeSubFolders) else AddStrArr(tmp, ABasePath); // sieve out folders that match criteria if (Length(splitIncluded) > 0) then begin for i := Low(tmp) to High(tmp) do for ii := Low(splitIncluded) to High(splitIncluded) do if (0 <> Pos(UpperCase(splitIncluded[ii]), UpperCase(tmp[i]))) then AddStrArr(Folders, tmp[i]); end else Folders := tmp; // remove unwanted folders from search if (Length(splitExcluded) > 0) then for i := High(Folders) downto Low(Folders) do for ii := Low(splitExcluded) to High(splitExcluded) do if (0 <> Pos(PathDelim + UpperCase(splitExcluded[ii]), UpperCase(Folders[i]))) then Delete(Folders, i, 1); SetLength(tmp, 0); // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin if (Length(AFileMask) > 0) then tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!) else tmp := FindExFiles(Folders[i]); for ii := Low(tmp) to High(tmp) do AddStrArr(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); end; I apology, please update that method like shown above and now it really should work, I've not tested it much with extra large filesystems, on a small one it works like it should. You can enter "Windows" or "windows" or just "win", everything that has this in name will be excluded from the deeper file search mechanism. When I got more free time I will continue making it better. Share this post Link to post
programmerdelphi2k 237 Posted May 29, 2023 (edited) 24 minutes ago, KodeZwerg said: When I got more free time I will continue making it better. After +10 minutes waiting, I had that stop it...!!! -- verify the "Range check error" I think that your approach of "excluding" the undesirable directories, should be done during the search of the files, and not in a previous or later step, because, in this way, you are doing a search in 2 or more steps, that is, first you are searching everything, then you will delete everything that is not desirable... So, you should do this exclusion of undesirables during the main search, avoiding a second or third action! I think your logic here is wrong! Since the owner of the post needs to find c:\*.*, your search is being carried out in all directories, and, only at the end, you are excluding "C:\Windows" from the directory, which further increases the task! Here on my PC, your search started at 3:26 pm, and I "STOP IT" 3:37 pm, and none resulted on listbox yet, using your latest "FindEx" update, CPU using 15~20% all the time! ... below, before your last FindEx update... Edited May 29, 2023 by programmerdelphi2k Share this post Link to post
KodeZwerg 54 Posted May 29, 2023 Please not use a full path at excluding, for that my code ain't designed yet. Share this post Link to post
programmerdelphi2k 237 Posted May 29, 2023 27 minutes ago, KodeZwerg said: AddStrArr my tip: Avoid the excessive usage of "SetLenght()", try define a conditicional for it, like: each 100...n items, use SetLenght()! that way, if exists 1000 object, then you'll have 10 SetLength() 1 Share this post Link to post
programmerdelphi2k 237 Posted May 29, 2023 1 minute ago, KodeZwerg said: for that my code ain't designed yet. You have to consider this, because the search must know the full path, to avoid excluding the search in a different subdirectory, for example: c:\Windows and c:\Other\Windows <--- are different things! 1 Share this post Link to post
programmerdelphi2k 237 Posted May 29, 2023 (edited) MEA CULPA: in my code propose I forgot verify about c:\Windows and c:\Other\Windows <--- are different things! --> sorry! 😝 if not(LLookFolderToSkip and MyFoldersToSkip(AFoldersToSkip, LSearchRecord.Name)) then <--- it should be: AFolderRoot + LSearchRecord.Name now, you need this: (or some way to do it automatically... MyFindFilePattern('D:\zzTest', ['*.*'], ['D:\zzTest\Windows'], LMyResult); Edited May 29, 2023 by programmerdelphi2k Share this post Link to post
KodeZwerg 54 Posted May 29, 2023 (edited) unit uFindEx; interface uses Winapi.Windows, System.SysUtils; type // My variant of an "StringList" TFindArray = TArray<string>; // array of WideString; function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; implementation const // missing FindEx flags FIND_FIRST_EX_CASE_SENSITIVE = $00000001; FIND_FIRST_EX_LARGE_FETCH = $00000002; FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004; // Small helper to add strings in my "StringList" procedure AddStrArr(var AArr: TFindArray; const AString: string); inline; var i: Integer; begin i := Length(AArr); SetLength(AArr, Succ(i)); AArr[i] := AString; end; // This method will crawl thru a folder and collect their names // IncludeSubFolders switch will get every folder, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path function FindExFolders(const ABasePath: string; const AInclusionList, AExclusionList: TFindArray; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp : TFindArray; i, ii : Integer; s:string; begin SetLength(Result, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + '*.*') ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..')) and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then begin if (Length(AInclusionList) > 0) then begin for i := Low(AInclusionList) to High(AInclusionList) do if (0 <> Pos(UpperCase(AInclusionList[i]), UpperCase(IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName))) then AddStrArr(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end else AddStrArr(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); if (Length(AExclusionList) > 0) then begin for i := High(Result) downto Low(Result) do for ii := Low(AExclusionList) to High(AExclusionList) do if (0 <> Pos(UpperCase(AExclusionList[ii]), UpperCase(Result[i]))) then Delete(Result, i, 1); end; end; until not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Result) to High(Result) do begin tmp := FindExFolders(Result[i], AInclusionList, AExclusionList, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddStrArr(Result, tmp[ii]); end; SetLength(tmp, 0); end; // This method will crawl thru a folder and collect their filenames // IncludeSubFolders switch will get every filename, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path + filename function FindExFiles(const ABasePath: string; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp, Folders : TFindArray; i, ii : Integer; begin SetLength(Result, 0); SetLength(Folders, 0); SetLength(tmp, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + AFileMask) ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..'))) then begin if (0 = (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) then AddStrArr(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); if (AIncludeSubFolders and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then AddStrArr(Folders, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end; until not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Folders) to High(Folders) do begin tmp := FindExFiles(Folders[i], AFileMask, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddStrArr(Result, tmp[ii]); end; SetLength(Folders, 0); SetLength(tmp, 0); end; // My variant of how a file search method can be done for windows systems // BasePath = where do we start at? eg "C:\Users" // FoldersMustExist = what foldername is a must for results? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // ExludedFolders = in what foldername you do not want to search? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // FileMask = what files you hunt for? eg "*.pas" // IncludeSubFolders = yes or no, you choose. False by default // based upon my "FindExFolders" and "FindExFiles" methods function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var tmp, Folders, Files: TFindArray; splitIncluded, splitExcluded: TFindArray; i, ii: Integer; begin SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); if (Length(AFoldersMustExist) > 0) then begin if (0 <> Pos(';', AFoldersMustExist)) then splitIncluded := AFoldersMustExist.Split([';']) else AddStrArr(splitIncluded, AFoldersMustExist); end; if (Length(AExludedFolders) > 0) then begin if (0 <> Pos(';', AExludedFolders)) then splitExcluded := AExludedFolders.Split([';']) else AddStrArr(splitExcluded, AExludedFolders); end; // collect folder(s) to work on if AIncludeSubFolders then Folders := FindExFolders(ABasePath, splitIncluded, splitExcluded, AIncludeSubFolders) else AddStrArr(Folders, ABasePath); // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin if (Length(AFileMask) > 0) then tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!) else tmp := FindExFiles(Folders[i]); for ii := Low(tmp) to High(tmp) do AddStrArr(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); end; end. Can you retry please @programmerdelphi2k @robertjohns, just replace the full units code with above. Thanks for tipp about SetLength() @programmerdelphi2k, will be added later, in above i put now the exclusions right into the searching job, should be in theory faster now 😛 Ps: Now it is working with a full given pathname for exclusion, eg: "c:\windows" Edited May 29, 2023 by KodeZwerg 1 Share this post Link to post
programmerdelphi2k 237 Posted May 29, 2023 10 minutes ago, KodeZwerg said: should be in theory faster now Now was quick NOTE: I didn't check if the 133,676 files were from c:\Windows or not... 😜 Share this post Link to post
KodeZwerg 54 Posted May 29, 2023 "Folder must exist" is currently not working, I will update but not today 😛 Share this post Link to post
KodeZwerg 54 Posted May 30, 2023 unit uFindEx; interface uses Winapi.Windows, System.SysUtils; type // My variant of an "StringList" TFindArray = TArray<string>; // array of WideString; function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; implementation const // missing FindEx flags FIND_FIRST_EX_CASE_SENSITIVE = $00000001; FIND_FIRST_EX_LARGE_FETCH = $00000002; FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004; // Small helper to add strings in my "StringList" procedure AddFindArray(var AFindArray: TFindArray; const AString: string); inline; var i: Integer; begin i := Length(AFindArray); SetLength(AFindArray, Succ(i)); AFindArray[i] := AString; end; // This method will crawl thru a folder and collect their names // The ExclusionList should contain full path names that be total excluded from search, by default everything is included // IncludeSubFolders switch will get every folder, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path function FindExFolders(const ABasePath: string = ''; const AExclusionList: TFindArray = []; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp : TFindArray; i, ii : Integer; s:string; begin SetLength(Result, 0); if ((ABasePath = '') or (not DirectoryExists(ABasePath))) then Exit; FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + '*.*') ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..')) and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then begin if (Length(AExclusionList) > 0) then begin for i := Low(AExclusionList) to High(AExclusionList) do if (0 = Pos(UpperCase(AExclusionList[i]), UpperCase(IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName))) then AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end else AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end; until (not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData)); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Result) to High(Result) do begin tmp := FindExFolders(Result[i], AExclusionList, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddFindArray(Result, tmp[ii]); end; SetLength(tmp, 0); end; // This method will crawl thru a folder and collect their filenames // IncludeSubFolders switch will get every filename, False by default // Based upon very fast FindEx Api (Windows) // The result will contain full path + filename function FindExFiles(const ABasePath: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var FindExHandle : THandle; Win32FindData : TWin32FindDataW; FindExInfoLevels: TFindexInfoLevels; FindExSearchOps : TFindexSearchOps; AdditionalFlags : DWORD; tmp, Folders : TFindArray; i, ii : Integer; begin SetLength(Result, 0); if ((ABasePath = '') or (not DirectoryExists(ABasePath))) then Exit; SetLength(Folders, 0); SetLength(tmp, 0); FindExInfoLevels := FindExInfoBasic; FindExSearchOps := FindExSearchLimitToDirectories; AdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; FindExHandle := Winapi.Windows.FindFirstFileExW( PWideChar(IncludeTrailingBackslash(ABasePath) + AFileMask) ,FindExInfoLevels, @Win32FindData, FindExSearchOps, nil ,AdditionalFlags); if (FindExHandle <> INVALID_HANDLE_VALUE) then begin repeat if ((Win32FindData.cFileName <> string('.')) and (Win32FindData.cFileName <> string('..'))) then begin if (0 = (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)) then AddFindArray(Result, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); if (AIncludeSubFolders and (0 <> (Win32FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY))) then AddFindArray(Folders, IncludeTrailingBackslash(ABasePath) + Win32FindData.cFileName); end; until (not Winapi.Windows.FindNextFileW(FindExHandle, Win32FindData)); Winapi.Windows.FindClose(FindExHandle); end; if AIncludeSubFolders then for i := Low(Folders) to High(Folders) do begin tmp := FindExFiles(Folders[i], AFileMask, AIncludeSubFolders); for ii := Low(tmp) to High(tmp) do AddFindArray(Result, tmp[ii]); end; SetLength(Folders, 0); SetLength(tmp, 0); end; // My variant of how a file search method can be done for windows systems // BasePath = where do we start at? eg "C:\Users" // FoldersMustExist = what foldername is a must for results? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // ExludedFolders = in what foldername you do not want to search? eg "Documents", can be left empty for all (seperate with ";" if more than 1) // FileMask = what files you hunt for? eg "*.pas" // IncludeSubFolders = yes or no, you choose. False by default // based upon my "FindExFolders" and "FindExFiles" methods function FindEx(const ABasePath: string; const AFoldersMustExist: string = ''; AExludedFolders: string = ''; const AFileMask: string = '*.*'; const AIncludeSubFolders: Boolean = False): TFindArray; var tmp, Folders, Files: TFindArray; splitIncluded, splitExcluded: TFindArray; i, ii: Integer; begin SetLength(Result, 0); SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); // prepare splittings if (Length(AFoldersMustExist) > 0) then begin if (0 <> Pos(';', AFoldersMustExist)) then splitIncluded := AFoldersMustExist.Split([';']) else AddFindArray(splitIncluded, AFoldersMustExist); end; if (Length(AExludedFolders) > 0) then begin if (0 <> Pos(';', AExludedFolders)) then splitExcluded := AExludedFolders.Split([';']) else AddFindArray(splitExcluded, AExludedFolders); end; // collect folder(s) to work on if AIncludeSubFolders then tmp := FindExFolders(ABasePath, splitExcluded, AIncludeSubFolders) else AddFindArray(tmp, ABasePath); // sieve out folders that match criteria if (Length(splitIncluded) > 0) then begin for i := Low(tmp) to High(tmp) do for ii := Low(splitIncluded) to High(splitIncluded) do if (0 <> Pos(UpperCase(splitIncluded[ii]), UpperCase(tmp[i]))) then AddFindArray(Folders, tmp[i]); end else Folders := tmp; // get files that matching the criteria for i := Low(Folders) to High(Folders) do begin if (Length(AFileMask) > 0) then tmp := FindExFiles(Folders[i], AFileMask) // do not enable the IncludeSubFolders switch here (!) else tmp := FindExFiles(Folders[i]); for ii := Low(tmp) to High(tmp) do AddFindArray(Files, tmp[ii]); end; Result := Files; SetLength(tmp, 0); SetLength(Folders, 0); SetLength(Files, 0); SetLength(splitIncluded, 0); SetLength(splitExcluded, 0); end; end. Fixed the "Folder must included" thingy, now it works pretty well for me. Share this post Link to post
Fr0sT.Brutal 900 Posted May 30, 2023 Why setting length to 0 at the start and end? Dynamic arrays are managed internally Share this post Link to post
KodeZwerg 54 Posted May 31, 2023 On 5/29/2023 at 6:20 PM, robertjohns said: Same result not excludes Does it now works for you? On 5/30/2023 at 9:42 AM, Fr0sT.Brutal said: Why setting length to 0 at the start and end? Dynamic arrays are managed internally Feel free to remove 🤭 Share this post Link to post
programmerdelphi2k 237 Posted June 1, 2023 (edited) @KodeZwerg @robertjohns a little less code... if we remove the frills, we have even a little less.... if we remove everything, we have even less in my tests all is working... type TFindFileDirectory = (ffdDirectory, ffdFile); TFindFilesDirectories = set of TFindFileDirectory; TArrObjectsFound = TArray<string>; const // missing FindEx flags FIND_FIRST_EX_CASE_SENSITIVE = $00000001; FIND_FIRST_EX_LARGE_FETCH = $00000002; FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY = $00000004; var LFindFileDirectory: TFindFilesDirectories; LDirRootToSearch : string = ''; function FindExcludingFolders(ARootDir: string; AListFolders: TArrObjectsFound): boolean; begin result := false; // if (ARootDir.IsEmpty) or (length(AListFolders) = 0) then exit; // for var F in AListFolders do if (LowerCase(F) = LowerCase(ARootDir)) then exit(true); end; procedure FindDirsRecursive( { } ARootDir: string; { } var ADirsFound, AFilesFound: TArrObjectsFound; { } AFindObjects: TFindFilesDirectories; { } ADirsExclude: TArrObjectsFound); var LFilename : PWideChar; LFIndexInfoLevels: TFindexInfoLevels; LFindFileData : TWin32FindData; // Pointer; LFindexSearchOps : TFindexSearchOps; // LSearchFilter : Pointer; = always null, for while in mswindows! LAdditionalFlags: cardinal; LFindResult : NativeUInt; // // LGetLastError : cardinal; LIsPointDirectory : boolean; LIsDirectory : boolean; LFileFound : string; LRootDirNormalized: string; LExcludeFolder : boolean; begin ARootDir := IncludeTrailingPathDelimiter(ARootDir); // for new IDEs LExcludeFolder := (length(ADirsExclude) > 0); // LFilename := PWideChar(ARootDir + '*.*'); LFIndexInfoLevels := _FINDEX_INFO_LEVELS.FindExInfoStandard; LFindexSearchOps := _FINDEX_SEARCH_OPS.FindExSearchLimitToDirectories; LAdditionalFlags := FIND_FIRST_EX_LARGE_FETCH or FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY; // LFindResult := Winapi.Windows.FindFirstFileEx( { } LFilename, { } LFIndexInfoLevels, { } @LFindFileData, { } LFindexSearchOps, { } nil { it should be NULL } , { } LAdditionalFlags); // try // LGetLastError := GetLastError; // if (LFindResult <> INVALID_HANDLE_VALUE) then begin repeat LFileFound := LFindFileData.cFileName; // LIsPointDirectory := ((LFileFound = '.') or (LFileFound = '..')); LIsDirectory := ((LFindFileData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0); LRootDirNormalized := ARootDir + LFileFound; // // either file or directory, all in a few lines of code! if not(LIsPointDirectory) then begin if LIsDirectory and (ffdDirectory in AFindObjects) then begin if not(LExcludeFolder and FindExcludingFolders(LRootDirNormalized, ADirsExclude)) then begin ADirsFound := ADirsFound + [LRootDirNormalized]; // FindDirsRecursive(LRootDirNormalized, ADirsFound, AFilesFound, AFindObjects, ADirsExclude); end; end else begin if (ffdFile in AFindObjects) then AFilesFound := AFilesFound + [LRootDirNormalized]; end; end; // until not Winapi.Windows.FindNextFile(LFindResult, LFindFileData); end; finally if (LFindResult <> INVALID_HANDLE_VALUE) then Winapi.Windows.FindClose(LFindResult); end; end; for test: var LArrFoundDirectories: TArrObjectsFound; LArrFoundFiles : TArrObjectsFound; begin LFindFileDirectory := LFindFileDirectory + [TFindFileDirectory.ffdDirectory, TFindFileDirectory.ffdFile]; // FindDirsRecursive(Edit1.Text, { } LArrFoundDirectories, { } LArrFoundFiles, { } LFindFileDirectory, { } ['d:\_WinBackups', 'd:\AndroidStudioSDK', 'd:\DelphiEditions', { } 'd:\RADStudioTests', 'd:\RADRX112Samples', 'd:\SDKsRAD']); Edited June 1, 2023 by programmerdelphi2k Share this post Link to post
KodeZwerg 54 Posted June 1, 2023 @programmerdelphi2k I am happy when you are happy. To me your way is useless, you lost what I was needing, finding specific files in specific folders. Share this post Link to post
programmerdelphi2k 237 Posted June 1, 2023 3 hours ago, KodeZwerg said: To me your way is useless, you lost what I was needing, finding specific files in specific folders. you're wrong, my code find any file where you desire! Share this post Link to post
KodeZwerg 54 Posted June 1, 2023 Let me tell it that way @programmerdelphi2k, with my posted source I was able to enter "documents" as an included folder-name and "*.pdf" as a file-mask (also "c:\windows" to exclude that folder) and as a result i get all "*.pdf" files that are inside of any "documents" folder. exemplary "c:\users\documents\manual.pdf" or "c:\users\public\documents\another.pdf" or "c:\users\username\documents\etc.pdf" ... How-to with your way? Share this post Link to post
programmerdelphi2k 237 Posted June 1, 2023 10 hours ago, KodeZwerg said: How-to with your way? it's quite simple: FindFirstFileEx accept: * and ? mask chars like D.O.S. or you can verify the files names before add in "AFilesFound" I forgot add this, but it's quite simple add it. 😋 Share this post Link to post
robertjohns 0 Posted June 13, 2023 On 5/29/2023 at 6:20 PM, KodeZwerg said: Yes, it was very complicated to fix. Uploaded a fully working Demo application based on my above mentioned code, added "Exclude" capabilities as you wanted. FindEx.zip Sorry but completely not working on Windows 7 32/64 bit Share this post Link to post
Sherlock 663 Posted June 14, 2023 I have a feeling the specifications have not been clear enough to the folks that answered, because https://stackoverflow.com/questions/76472056/exclude-specific-folder-from-file-search-in-delphi Share this post Link to post
KodeZwerg 54 Posted June 23, 2023 (edited) On 6/13/2023 at 6:34 PM, robertjohns said: Sorry but completely not working on Windows 7 32/64 bit https://support.microsoft.com/en-us/windows/windows-7-support-ended-on-january-14-2020-b75d4580-2cc7-895a-2c9c-1466d9a53962 It will also not work in Windows XP or Windows 95. Edited June 23, 2023 by KodeZwerg Share this post Link to post