- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
I have been looking for a routine that will find all the occurrences of a file in a directory tree, but there are no QuickWin functions that are useful. At first I successfully used the DOS command
dir filename /b/l/s/o:n /a:-d >c:dirlist.txt'
called by SYSTEMQQ. This works well and with wildcards, but flashes up a DOS box whilst searching.
I then wrote a successful recursive routine FindFileinTree using the WIN APIs FindFirstFile and FindNextFile ? but I am still working on the wildcards side of it.
Then I chanced upon SearchTreeForFile in imagehlp.dll. This is not one for which CVF has an interface ? indeed I cannot even find it in either of JR Simon?s API Superbibles. I applied my considerable degree of ignorance of WIN APIs to hacking a working interface for it, and found that it will only find the first occurrence of a file, and does not work with wildcards.
Does anyone know if it is possible to use SearchTreeForFile or any other similar routine to find all the occurrences of a file in a tree?
Bear of little brain
dir filename /b/l/s/o:n /a:-d >c:dirlist.txt'
called by SYSTEMQQ. This works well and with wildcards, but flashes up a DOS box whilst searching.
I then wrote a successful recursive routine FindFileinTree using the WIN APIs FindFirstFile and FindNextFile ? but I am still working on the wildcards side of it.
Then I chanced upon SearchTreeForFile in imagehlp.dll. This is not one for which CVF has an interface ? indeed I cannot even find it in either of JR Simon?s API Superbibles. I applied my considerable degree of ignorance of WIN APIs to hacking a working interface for it, and found that it will only find the first occurrence of a file, and does not work with wildcards.
Does anyone know if it is possible to use SearchTreeForFile or any other similar routine to find all the occurrences of a file in a tree?
Bear of little brain
Lien copié
6 Réponses
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
AFAIK no -- solution with recursive FindFirstFile/FindNextFile is "classic". I'd suggest having two "interwoven" searches instead of one (i.e. two FindFirstFiles with two separate handles) -- one recursively searching for directories (*.* with WFD%dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY), the second searching for files within one directory which satisfy given file-spec.
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Jugoslav,
Many thanks for your helpful reply. Do you recommend a two-thread process because it is faster or for another reason? Two threads is about one more than I can hack.
I find it strange that a single WIN API does not exist for this purpose, which is exactly what Windows Explorer does in searching for a file. SearchTreeForFile is OK if you are certain there is only one occurrence of a file, but even that is buried away. Anyway, I am a firm believer in Paranoia Programming, and with Windows, copies of files can proliferate.
So I think that on this one I will retire hurt and use my home-brewed version which currently can't deal with partial paths.
Bear of little Brain
Many thanks for your helpful reply. Do you recommend a two-thread process because it is faster or for another reason? Two threads is about one more than I can hack.
I find it strange that a single WIN API does not exist for this purpose, which is exactly what Windows Explorer does in searching for a file. SearchTreeForFile is OK if you are certain there is only one occurrence of a file, but even that is buried away. Anyway, I am a firm believer in Paranoia Programming, and with Windows, copies of files can proliferate.
So I think that on this one I will retire hurt and use my home-brewed version which currently can't deal with partial paths.
Bear of little Brain
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
No, no, I didn't meant threads, but rather something along these lines (off the top of my head, so excuse me for errors)
Hope you get the idea. (I used C_TRIM for something that returns string up to the first CHAR(0)). My suggestion was actually related with your "home-brew" idea -- I just meant that using two FindFirstFiles should solve the problem entirely, including wildcard stuff.
Perhaps the code above could be speeded up if one is sure that subdirectories are always found first (because the outer loop as is now will check for all files and subdirectories), but docs do not guarantee that.
HTH
Jugoslav
RECURSIVE SUBROUTINE SearchTree(szDirName, szFileSpec)
CHARACTER(*):: szDirName, &
szFileSpec !file name including wildcards
INTEGER:: hFindDir, & !For traversing subdirectories
hFindFile !For traversing this directory
TYPE (T_WIN32_FIND_DATA):: WFDdir, WFDfile
hFindDir=FindFirstFile(C_TRIM(szDirName)//"*.*"C, WFDdir)
bFoundDir =.TRUE.
DO WHILE (hFindDir/=INVALID_HANDLE_VALUE .AND. bFoundDir)
!Now search for files in this directory
hFindFile = FindFirstFile(C_TRIM(szDirName)//""//szFileSpec, WFDfile)
bFoundFile=.TRUE.
DO WHILE (hFindFile/=INVALID_HANDLE_VALUE .AND. bFoundFile)
!Do something with WFDfile%cFileName here
bFoundFile = FindNextFile(hFindFile, WFDfile)
END DO
!Find next directory
hFindDir=FindNextFile(hFindDir, WFDdir)
IF (IAND(WFDdir%dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY).NE.0) THEN
CALL SearchTree(WFDdir%cFileName, szFileSpec)
END IF
END DO
Hope you get the idea. (I used C_TRIM for something that returns string up to the first CHAR(0)). My suggestion was actually related with your "home-brew" idea -- I just meant that using two FindFirstFiles should solve the problem entirely, including wildcard stuff.
Perhaps the code above could be speeded up if one is sure that subdirectories are always found first (because the outer loop as is now will check for all files and subdirectories), but docs do not guarantee that.
HTH
Jugoslav
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Just spotted an obvious logical error -- there shouldn't be two embedded loops, but two consecutive loops, the one being inner now should be first... see what I mean...
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Jugooslav,
Many thanks for the code. With your later correction, it is basically what I have done, but the use of another FindFirst File call with a different selection criterion fixes my wildcard problem. Your code is also rather more elegant than mine, because I am not yet comfortable with these NUL-terminated strings.
Bear of little brain
Many thanks for the code. With your later correction, it is basically what I have done, but the use of another FindFirst File call with a different selection criterion fixes my wildcard problem. Your code is also rather more elegant than mine, because I am not yet comfortable with these NUL-terminated strings.
Bear of little brain
- Marquer comme nouveau
- Marquer
- S'abonner
- Sourdine
- S'abonner au fil RSS
- Surligner
- Imprimer
- Signaler un contenu inapproprié
Jugoslav,
I append a working version of FindFileInTree, which can work from the root directory down. I made some changes to avoid trouble with the '.' & '..' at the start of every directory, also to the logic on the last 'do while' to cater for empty directories. Being fairly fresh from the mill, it is not yet very well tested, so please to you and others, let me know what the bugs are.
Thanks again for your help.
PS. It works OK on the wildcards that I tested.
I append a working version of FindFileInTree, which can work from the root directory down. I made some changes to avoid trouble with the '.' & '..' at the start of every directory, also to the logic on the last 'do while' to cater for empty directories. Being fairly fresh from the mill, it is not yet very well tested, so please to you and others, let me know what the bugs are.
Thanks again for your help.
!
!-------------------------------------------------------------------------------
recursive subroutine FindFileInTree(CurDir, FileName, Path, nPath)
! Searches directory CurDir for file FileName and puts its path into character
! array Path, incrementing nPath by one. It then searches any subdirectories
! using a recursive call. Set nPath to zero before calling.
!-------------------------------------------------------------------------------
use kernel32, only : FILE_ATTRIBUTE_DIRECTORY, FindFirstFile, FindNextFile, &
INVALID_HANDLE_VALUE, T_WIN32_FIND_DATA
use winfns, only : C_TRIM ! Returns string with Nul trimmed off.
implicit none
character(*), intent(in) :: CurDir
! Nul-terminated string containing start directory path.
character(*), intent(in) :: FileName
! Nul-terminated string containing filename including wildcards.
character(*), intent(inout) :: Path(*)
! Array of paths for files found (Nul-terminated strings).
integer(4), intent(inout) :: nPath
! Number of files found.
!
integer(4) hFindDir, hFindFile
logical(4) bFoundDir, BFoundFile
TYPE (T_WIN32_FIND_DATA) WFDdir, WFDfile
!
hFindFile = FindFirstFile(C_TRIM(CurDir)//""//FileName,WFDfile)
bFoundFile = .TRUE.
do while (hFindFile /= INVALID_HANDLE_VALUE .and. bFoundFile)
nPath = nPath+1
Path(nPath) = C_TRIM(CurDir)//""//WFDfile.cFileName
bFoundFile = FindNextFile(hFindFile,WFDfile)
end do
!
! The next two lines read in the '.' & '..' at the top of every directory.
!
hFindDir = FindFirstFile(C_TRIM(CurDir)//"*.*"C, WFDdir)
bFoundDir = FindNextFile(hFindDir,WFDDir)
bFoundDir = .TRUE.
do while (hFindDir/=INVALID_HANDLE_VALUE .AND. bFoundDir)
bFoundDir = FindNextFile(hFindDir,WFDDir)
if (WFDdir.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &
.AND. bFoundDir) then
call FindFileInTree(C_TRIM(CurDir)//""//WFDdir.cFileName,FileName, &
Path,nPath)
end if
end do
return
end subroutine FindFileInTree
PS. It works OK on the wildcards that I tested.
Répondre
Options du sujet
- S'abonner au fil RSS
- Marquer le sujet comme nouveau
- Marquer le sujet comme lu
- Placer ce Sujet en tête de liste pour l'utilisateur actuel
- Marquer
- S'abonner
- Page imprimable