Jump to content

Recursive Folder Search


Somerset
 Share

Recommended Posts

this RecursiveDir.au3 searches and returns and array of files and folders.

From a target folder you select. Please feel free to let me know how it works for you other than that enjoy...

Thanks Larry alot.

;;; RecursiveDir.au3;;;
#include-once
;
; the target folder will be recursively searched through
; and returns an array of files and folder together with full path.
; thanks in big part to Larry for the script which i modified
; useage : _Recursive($Sourcedir)
; please sectect only folders not drive letters by themselves.
; Beerman
;------------------------------------------------------------------------------------
Func _Recursive($Sourcedir)
    $a = 0
    $f = 0
    $d = 0
    $grand = ""
    While 1
        $Fold = $Sourcedir
        
        $reject = StringLen($Fold)
        If $reject = 3 Then
            MsgBox(0, 'Rejected', "This routine is only meant for folders only. Slect Again")
            $dirrejected = FileSelectFolder("Choose a folder this time not a drive letter.", "")
            If $dirrejected = "" Then Exit
            $Sourcedir = $dirrejected
        Else
            
            
            $Stack = $Fold & ">"
            $FileList = $Fold & ">"
            While $Stack <> ""
                $root = StringLeft($Stack, StringInStr($Stack, ">") - 1) & "\"
                $Stack = StringTrimLeft($Stack, StringInStr($Stack, ">"))
                $h = FileFindFirstFile($root & "*.*")
                If $h > - 1 Then
                    $FileFound = FileFindNextFile($h)
                    While Not @Error And $FileFound <> ""
                        If $FileFound <> "." And $FileFound <> ".." And _
                                StringInStr(FileGetAttrib($root & $FileFound), "D") Then
                            $Stack = $Stack & $root & $FileFound & ">"
                            
                            $FileList = $FileList & $root & $FileFound & "<"
                            $d = $d + 1
                            $a = $a + 1
                        Else
                            
                            
                            If $FileFound = "." Or $FileFound = ".." Then
                            Else
                                $f = $f + 1
                                $a = $a + 1
                                $FileList = $FileList & $root & $FileFound & "<"
                            EndIf
                            
                        EndIf
                        
                        $len = StringLen($FileList)
                        If $len > 10000 Then
                            $grand = $grand & $FileList
                            $FileList = ""
                        Else
                        EndIf
                        
                        ToolTip("Building List: Files-" & $f & " Folders-" & $d & " Total-" & $a, 0, 0)
                        $FileFound = FileFindNextFile($h)
                    WEnd
                    FileClose($h)
                EndIf
            WEnd
            $grand = $grand & $FileList
            $FileList = $grand
            $cleanup = StringReplace($FileList, ">", "<")
            $outputsubdirs = StringSplit($cleanup, "<", 1)
            Return $outputsubdirs
            Exit
        EndIf
    WEnd
EndFunc  ;==>_Recursive
Edited by beerman
Link to comment
Share on other sites

here is a recursive folder to folder copy with a progress bar.

#include "RecursiveDir.au3"
$dir = FileSelectFolder("Choose a Folder to copy.", "")
$dirdestination = FileSelectFolder("Choose a Destination Folder.", "")
ProgressOn("Files Copying", "Please be patient", "0 percent")
$all = _Recursive ($dir)
$Folder = $all[1]
While 1
    $Source = StringInStr($Folder, "\")
    If $Source = 0 Then
        ExitLoop
    Else
        $Folder = StringTrimLeft($Folder, 1)
    EndIf
WEnd
$searchanddestroy = StringReplace($all[1], $Folder, "")


$z = $all[0] - 1
$x = 0
$CountLines = $all[0]
$CountLines = $CountLines / 100
If $CountLines < 1 Then
    $CountLines = $CountLines + 1
Else
EndIf
$wholenumber = $CountLines
While 1
    $counter = StringIsDigit($wholenumber)
    If $counter = 0 Then
        $doublechecking = StringTrimRight($wholenumber, 1)
        $wholenumber = $doublechecking
    Else
        ExitLoop
    EndIf
WEnd
$zed = 1
$beta = 0
While $z <> - 1
    $beta = $beta + 1
    For $zed = 1 To $wholenumber
        $x = $x + 1
        $z = $z - 1
        If @error = 1 Then ExitLoop
        If $z = -1 Then ExitLoop
        $typeof = FileGetAttrib($all[$x])
        If $typeof = "D" Then
            $resultingdir = StringReplace($all[$x], $searchanddestroy, "")
$showing = $resultingdir
While 1
    $Source = StringInStr($showing, "\")
    If $Source = 0 Then
        ExitLoop
    Else
        $showing = StringTrimLeft($showing, 1)
    EndIf
WEnd

ProgressSet($beta, $beta & " percent", $showing)
            DirCreate($dirdestination & "\" & $resultingdir)
        Else
            $resultingfile = StringReplace($all[$x], $searchanddestroy, "")
$showing = $resultingfile
While 1
    $Source = StringInStr($showing, "\")
    If $Source = 0 Then
        ExitLoop
    Else
        $showing = StringTrimLeft($showing, 1)
    EndIf
WEnd

ProgressSet($beta, $beta & " percent", $showing)
            FileCopy($all[$x], $dirdestination & "\" & $resultingfile)
        EndIf
    Next
    If @error = -1 Then ExitLoop
    If $beta <> 101 And $beta < 101 Then
Sleep(100)
ProgressSet($beta, $beta & " percent", "Files Coping. ")        
    Else
$beta = $beta - 2
    EndIf
WEnd
ProgressSet(100, "Done", "Complete")
ProgressOff()
Edited by beerman
Link to comment
Share on other sites

I hapy speeded up the recursive search alittle. a folder that once took me 2 or more minutes to build and array, now only takes about 7 seconds. i fiddled around and found out that if the string sized is trimmed down , every so often it keeps the search speed way up. an array of 100,000+ seems to bog down the search so i told it if greater than 10,000 tranfer the content to another varible then continue the search. it speeds it up a lot doing this. i also modified the copy progress script to display the file that is being copied. I also added a tool tip to the recursive it gives you a count of the folders and files found. i find it to make it easier for the waiting procress if alot of files are involved. enjoy ;) the scripts are above in the first two posts...

Link to comment
Share on other sites

well i wanted to do it all without the assisst of dos and having to write it to a file. it is all done in memory with autoit.

dos doesnt need to write a file ... (STD I/O)

but if you had fun doing it ;)

thats what its all about.

Edited by w0uter

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

oh i know your right there it was fun. i also did it so some of the newbs don't have to do it.

besides if i figue out a way faster than dos then woohoo. i am gonna keep plugging away at it until.

either until i do make it faster or i go bald from trying to do it.

Link to comment
Share on other sites

try to be faster then this.

(finds all the .bat's in the C: drive in like 944 ms on my pc)

Func _FileSearch($s_Mask = '')
    Local $s_Buf = '', $i_Pid = Run(@ComSpec & ' /c dir /B /S "' & $s_Mask & '"', @WorkingDir, @SW_HIDE, 2)
    ProcessSetPriority($i_Pid, 5)
    While Not @error
        $s_Buf &= StdoutRead ($i_Pid)
    WEnd
    Return StringSplit(StringTrimRight($s_Buf, 2), @CRLF, 1)
EndFunc;==>_FileSearch

$t = TimerInit()
$var = _FileSearch('C:\*.bat')
ConsoleWrite(Timerdiff($t) & @CRLF)

For $i = 1 to $var[0]
    ConsoleWrite($var[$i] & @LF)
Next
Edited by w0uter

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

w0uter, one small suggestion -- wrapping the search mask with double quotes (for successful searches when using spaces):

$i_Pid = Run(@ComSpec & ' /c dir /B /S "' & $s_Mask & '"', @WorkingDir, @SW_HIDE, 2)
Link to comment
Share on other sites

  • 4 weeks later...

if i search on "E:\*.au3"

larry: 7845.45631005728

mine: 1065.01133811206

Well that's not fair! B)

Hardly a worthwhile comparison unless both of the following are true:

1. Your computer has exactly the same files/configuration/hardware as Larry's

2. Your buffer didn't kick in to change the results (specially if it's larger than Larry's)

Ok well that last one didn't quite come out the way I wanted but you understand :o

So obviously running from a Dos console is faster, but then what's the use if you want to work on each file as they are found? There's obviously STDIO but I would still rather have AutoIT handle the whole thing itself.

BTW I'm not sure who's got the paternity of this idea but the first time I saw it it was from Jos VanderZande.

P.S.: Dunno when it's going to be finished but I'm working on a way of encapsulating the whole thing in a function. The hard part is handling the filespecs (*.*) since if you put a filespec in this search function (say, "*.au3"), you'll obviously miss the subfolders (hence, no recursivity).

I am endeavoring, ma'am, to construct a mnemonic circuit using stone knives and bearskins.SpockMy UDFs:Deleted - they were old and I'm lazy ... :)My utilities:Comment stripperPolicy lister 1.07AutoIT Speed Tester (new!)

Link to comment
Share on other sites

Celeri:

I am looking forward to your function. It would be handy to be able to search folders and modify files from within AutoIt. I would like to write an encryption script, but my problelm is finding all of the file names in the folders. Your script would be of help to me.

Link to comment
Share on other sites

1. i meant larry's function and my function. not our pc's B)

3. if you want to use the results just use a for loop after the call to loop through the path's

and im sorry but i dont understand the rest of your post :o

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

@wOuter

Yep yours is faster...way faster...I must have got them mixed up when I was testing.

-Livewire

In my own tests, the _FileSearch was faster (about twice as fast) but failed to list a couple of subdirs finding a total of 284.630588524519 count=38

while RecursDir found all the files and subdirs 443.834342074202 count=71

Lee Cole

Talking Clockhttp://www.autoitscript.com/forum/index.php?showtopic=20751Talking Headlineshttp://www.autoitscript.com/forum/index.php?showtopic=20655Sometimes, I sits and thinkssometimes, I just sits

Link to comment
Share on other sites

1. i meant larry's function and my function. not our pc's B)

3. if you want to use the results just use a for loop after the call to loop through the path's

and im sorry but i dont understand the rest of your post :graduated:

uhmmm you're missing point 2 :)

My point was the following (and hopefully I can say something clearly this time - man it's hard!)

Ok two scenarios

The first, DOS-based way of doing things

1. Get data from "DIR *.* /S > dir.txt"

2. ... or get information from STDIO

3. Process information

4. Run a function on each entry

And the complete AutoIT way

1. Start filesearch

2. Get individual filenames

3. Operate on each file

4. Loop until finished.

While AutoIT will still be slower in the end, I reckon the AutoIT way still holds many advantages. I have integrated this function in my stuff for a while now and I still am very satisfied with it's speed.

Don't forget also that STDIO has a serious problem. My WinXP is in french and if I have files and folders with accents, they come out as garbage and need to be "translated". And so far I've tried every single dirty trick I could come up with and got only mitigated results (for some reason not all DOS programs accept to play nice with the code page function).

So there you have it :o

Gotta go, I have some base64 butt to kick :D

I am endeavoring, ma'am, to construct a mnemonic circuit using stone knives and bearskins.SpockMy UDFs:Deleted - they were old and I'm lazy ... :)My utilities:Comment stripperPolicy lister 1.07AutoIT Speed Tester (new!)

Link to comment
Share on other sites

  • 7 months later...

Beerman - I know it's been a while since you wrote this and was wondering if there are any updates. I'm interested in generating a dirlist of all files and using DOS am running at 200K/min. Currently your routine is at about 77K/min. Pretty good speed however on a large disk (400GB) I have over 1.2M files so either way it's taking 5 minutes just to build the dirlist. Thanks. ahha

this RecursiveDir.au3 searches and returns and array of files and folders.

From a target folder you select. Please feel free to let me know how it works for you other than that enjoy...

Thanks Larry alot.

;;; RecursiveDir.au3;;;
#include-once
;
; the target folder will be recursively searched through
; and returns an array of files and folder together with full path.
; thanks in big part to Larry for the script which i modified
; useage : _Recursive($Sourcedir)
; please sectect only folders not drive letters by themselves.
; Beerman
;------------------------------------------------------------------------------------
Func _Recursive($Sourcedir)
    $a = 0
    $f = 0
    $d = 0
    $grand = ""
    While 1
        $Fold = $Sourcedir
        
        $reject = StringLen($Fold)
        If $reject = 3 Then
            MsgBox(0, 'Rejected', "This routine is only meant for folders only. Slect Again")
            $dirrejected = FileSelectFolder("Choose a folder this time not a drive letter.", "")
            If $dirrejected = "" Then Exit
            $Sourcedir = $dirrejected
        Else
            
            
            $Stack = $Fold & ">"
            $FileList = $Fold & ">"
            While $Stack <> ""
                $root = StringLeft($Stack, StringInStr($Stack, ">") - 1) & "\"
                $Stack = StringTrimLeft($Stack, StringInStr($Stack, ">"))
                $h = FileFindFirstFile($root & "*.*")
                If $h > - 1 Then
                    $FileFound = FileFindNextFile($h)
                    While Not @Error And $FileFound <> ""
                        If $FileFound <> "." And $FileFound <> ".." And _
                                StringInStr(FileGetAttrib($root & $FileFound), "D") Then
                            $Stack = $Stack & $root & $FileFound & ">"
                            
                            $FileList = $FileList & $root & $FileFound & "<"
                            $d = $d + 1
                            $a = $a + 1
                        Else
                            
                            
                            If $FileFound = "." Or $FileFound = ".." Then
                            Else
                                $f = $f + 1
                                $a = $a + 1
                                $FileList = $FileList & $root & $FileFound & "<"
                            EndIf
                            
                        EndIf
                        
                        $len = StringLen($FileList)
                        If $len > 10000 Then
                            $grand = $grand & $FileList
                            $FileList = ""
                        Else
                        EndIf
                        
                        ToolTip("Building List: Files-" & $f & " Folders-" & $d & " Total-" & $a, 0, 0)
                        $FileFound = FileFindNextFile($h)
                    WEnd
                    FileClose($h)
                EndIf
            WEnd
            $grand = $grand & $FileList
            $FileList = $grand
            $cleanup = StringReplace($FileList, ">", "<")
            $outputsubdirs = StringSplit($cleanup, "<", 1)
            Return $outputsubdirs
            Exit
        EndIf
    WEnd
EndFunc ;==>_Recursive
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...