Sign in to follow this  
Followers 0
Kudzu309

Recursive search - function calling itself - something changed?

5 posts in this topic

#1 ·  Posted (edited)

I've written and used an AutoIt script in the past to recursively search through directories and delete files that are X days old. As the script is searching through a directory, when it finds another directory it calls itself (it's is a function). Previously when it called itself it would wait until that instance completed before continuing, but now that I'm at the latest version of AutoIt (v3.3) it seems that it no longer waits. Is this a change in the way AutoIt works or compiles? The script is running on a Windows XP box.

Also, I'm aware of this script that recursively searches a directory, but it would require a major re-write of my code, so I'd rather just fix what I've already written as it is much simpler

Here is a slimmed-down example of my code:

Searchdir (somedir)
[Display log file]

        Func SearchDir($dir)
            $filehandle = FileFindFirstFile($dir & "*")
            If $filehandle = -1 Then Return
            While 1
                $file = FileFindNextFile($filehandle)
                If @error Then ExitLoop
                If StringInStr(FileGetAttrib($dir & $file), "D") > 0 Then ;<------ checks if file is a directory
                    SearchDir($dir & $file)
                Else
                    PurgeOldFiles($dir, $file, $size, $shortdir);<----- function that deletes the file if it is X days old
                EndIf
            WEnd
            Return
        EndFunc

The reason I know it's exiting early is that after the routine that kicks off the search it displays a log file of what was deleted and it's now displaying an empty log file while it's still searching through directories.

Thanks in advance for your help!

Edited by Kudzu309

Share this post


Link to post
Share on other sites



_FileListToArrayEx() by SmO_keN


When the words fail... music speaks

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Kudzu309,

At first glance the function does not seem wrong - and you say you have been using it before. Certainly AutoIt 3.3.0.0 does not cause the problem or half of my scripts would have malfunctioned also! Perhaps the problem is not in the recursive function.

I assume that $size and $shortdir are declared elsewhere. Are you sure that they are being set correctly? If the function never finds a match to purge.......

I will play with your code a little more and see if anything else occurs to me.

By the way, I notice that you never FileClose the search handle. From the Helpfile: "When you have finished searching with the FileFind... functions you must call FileClose() to release the search handle." I do not believe it has anything to do with this problem, but it is good practice not to hog the handles (sounds pretty revolting when put like that!).

M23

Edit: Something has just struck me. If you are writing your Logfile after calling the function the first time, your log file will not be written until the whole recursive bit finishes and the function rejoins the main script. So it is hardly surprising if the log file stays blank while the recursive bit is going on. Or is this because you have "slimmed-down" a bit too much?

Edited by Melba23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I've written and used an AutoIt script in the past to recursively search through directories and delete files that are X days old. As the script is searching through a directory, when it finds another directory it calls itself (it's is a function). Previously when it called itself it would wait until that instance completed before continuing, but now that I'm at the latest version of AutoIt (v3.3) it seems that it no longer waits. Is this a change in the way AutoIt works or compiles? The script is running on a Windows XP box.

Also, I'm aware of this script that recursively searches a directory, but it would require a major re-write of my code, so I'd rather just fix what I've already written as it is much simpler

Here is a slimmed-down example of my code:

Searchdir (somedir)
  [Display log file]
  
          Func SearchDir($dir)
              $filehandle = FileFindFirstFile($dir & "*")
              If $filehandle = -1 Then Return
              While 1
                  $file = FileFindNextFile($filehandle)
                  If @error Then ExitLoop
                  If StringInStr(FileGetAttrib($dir & $file), "D") > 0 Then;<------ checks if file is a directory
                      SearchDir($dir & $file)
                  Else
                      PurgeOldFiles($dir, $file, $size, $shortdir);<----- function that deletes the file if it is X days old
                  EndIf
              WEnd
              Return
          EndFunc

The reason I know it's exiting early is that after the routine that kicks off the search it displays a log file of what was deleted and it's now displaying an empty log file while it's still searching through directories.

Thanks in advance for your help!

The code does look correct but I don't think it is. I had a similar problem when I first used FileFindNext and FileFindFirst and that was when I found AutoIt in 2004.

Try this

$Somedir = "G:\";<--how I tested
 Searchdir ($somedir)
;[Display log file]
 
         Func SearchDir($dir)
             filechangedir($dir)
           ;ConsoleWrite("dir = " & $dir & @CRLF)
             $filehandle = FileFindFirstFile("*.*");$dir & "*.*")
             If $filehandle = -1 Then Return
             While 1
                 $file = FileFindNextFile($filehandle)
                 If @error Then ExitLoop
                 If $file <> '.' And $file <> '..' Then
                     $att = FileGetAttrib($file);$dir &  $file)
                   ;ConsoleWrite("attrib = " & $att & "for file " & $file & @CRLF)
                 If StringInStr($att, "D") > 0 Then;<------ checks if file is a directory
                   ;ConsoleWrite("found dir = " & $file & @CRLF)
                     SearchDir($dir & "\" & $file)
                     filechangedir($dir)
              ; Else;<---------------------- 2 lines commented out so I could test
               ;    PurgeOldFiles($dir, $file, $size, $shortdir);<----- function that deletes the file if it is X days old
              EndIf
              EndIf
             WEnd
             Return
         EndFunc
Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Hi,

here another way for recursive search:

;==================================================================================================
; Function Name:   _GetFilesFolder_Rekursiv($sPath [, $sExt='*' [, $iDir=-1 [, $iRetType=0 ,[$sDelim='0']]]])
; Description:     Recursive listing of files and/or folders
; Parameter(s):    $sPath     Basicpath of listing ('.' -current path, '..' -parent path)
;                  $sExt      Extension for file selection '*' or -1 for all (Default)
;                  $iDir      -1 Files+Folder(Default), 0 only Files, 1 only Folder
;      optional:   $iRetType  0 for Array, 1 for String as Return
;      optional:   $sDelim    Delimiter for string return
;                             0 -@CRLF (Default)  1 -@CR  2 -@LF  3 -';'  4 -'|'
; Return Value(s): Array (Default) or string with found pathes of files and/or folder
;                  Array[0] includes count of found files/folder
; Author(s):       BugFix (bugfix@autoit.de)
;==================================================================================================
Func _GetFilesFolder_Rekursiv($sPath, $sExt='*', $iDir=-1, $iRetType=0, $sDelim='0')
    Global $oFSO = ObjCreate('Scripting.FileSystemObject')
    Global $strFiles = ''
    Switch $sDelim
        Case '1'
            $sDelim = @CR
        Case '2'
            $sDelim = @LF
        Case '3'
            $sDelim = ';'
        Case '4'
            $sDelim = '|'
        Case Else
            $sDelim = @CRLF
    EndSwitch
    If ($iRetType < 0) Or ($iRetType > 1) Then $iRetType = 0
    If $sExt = -1 Then $sExt = '*'
    If ($iDir < -1) Or ($iDir > 1) Then $iDir = -1
    _ShowSubFolders($oFSO.GetFolder($sPath),$sExt,$iDir,$sDelim)
    If $iRetType = 0 Then
        Local $aOut
        $aOut = StringSplit(StringTrimRight($strFiles, StringLen($sDelim)), $sDelim, 1)
        If $aOut[1] = '' Then 
            ReDim $aOut[1]
            $aOut[0] = 0
        EndIf
        Return $aOut
    Else
        Return StringTrimRight($strFiles, StringLen($sDelim))
    EndIf
EndFunc

Func _ShowSubFolders($Folder, $Ext='*', $Dir=-1, $Delim=@CRLF)
    If Not IsDeclared("strFiles") Then Global $strFiles = ''
    If ($Dir = -1) Or ($Dir = 0) Then 
        For $file In $Folder.Files
            If $Ext <> '*' Then
                If StringRight($file.Name, StringLen($Ext)) = $Ext Then _
                    $strFiles &= $file.Path & $Delim
            Else
                $strFiles &= $file.Path & $Delim
            EndIf
        Next
    EndIf
    For $Subfolder In $Folder.SubFolders
        If ($Dir = -1) Or ($Dir = 1) Then $strFiles &= $Subfolder.Path & '\' & $Delim
        _ShowSubFolders($Subfolder, $Ext, $Dir, $Delim)
    Next
EndFunc


; Or if you search an special file, a very fast method:

;===============================================================================
; Function Name:   _SearchTreeForFile($sRootPath, $sFileName)
; Description::    Filesearch in an given path and all subs
; Parameter(s):    $sRootPath    Basicpath for search
;                  $sFileName    Name of searched file
; Return Value(s): found         Path of searched file
;                  not found     0
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _SearchTreeForFile($sRootPath, $sFileName)
    If StringRight($sRootPath, 1) <> '\' Then $sRootPath &= '\'
    Local $sOutputPathBuffer = ''
    Local $aRet = DllCall("imagehlp", 'long', 'SearchTreeForFile', 'str', _
            $sRootPath, 'str', $sFileName, 'str', $sOutputPathBuffer)
    If $aRet[0] = 1 Then
        Return $aRet[3]
    Else
        Return 0
    EndIf
EndFunc  ;==>_SearchTreeForFile
Edited by BugFix

Best Regards BugFix  

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0