Jump to content

Search folders recursively


Recommended Posts

I have a folder that contains all of my music in seperate folders and i am trying to make a script that when a user enteres all or part of a artist it will search the parent folder recursively to search all folders and return any results it may find from my query.

Im sure this has to be done before, i just can't figure it out.

Any ideas how to search folders recursively?

Edited by blackey
Link to comment
Share on other sites

This script recuses a directory or drive and generates a logfile, I'm sure you can modify it to your needs

$logfile = FileOpen ("C:\DirectoryList.txt",2)
Search ("c:");replace with your search directory

Func Search($current)

    Local $search = FileFindFirstFile($current & "\*.*")
    While 1
        Dim $file = FileFindNextFile($search)
        If @error Or StringLen($file) < 1 Then ExitLoop
        If Not StringInStr(FileGetAttrib($current & "\" & $file), "D") And ($file <> "." Or $file <> "..") Then
        
        If $current & "\" & $file <> "C:\DirectoryList.txt"  then FileWriteLine ($logfile,$current & "\" & $file)
            
        EndIf
        If StringInStr(FileGetAttrib($current & "\" & $file), "D") And ($file <> "." Or $file <> "..") Then
            Search($current & "\" & $file)
            
        EndIf
    WEnd
    FileClose($search)

EndFunc

Func OnAutoitExit()
    FileClose ($logfile)
EndFunc
Link to comment
Share on other sites

This might be of more use, based on the above

Search ("c:", "Artist");replace with your search directory and Part of file name

Func Search($current,$searchQuery)

    Local $search = FileFindFirstFile($current & "\*.*")
    While 1
        Dim $file = FileFindNextFile($search)
        If @error Or StringLen($file) < 1 Then ExitLoop
        If Not StringInStr(FileGetAttrib($current & "\" & $file), "D") And ($file <> "." Or $file <> "..") Then

            If StringInStr($current & "\" & $file, $searchQuery) then 
                MsgBox (0, "Has the searchQuery " & $searchQuery, $current & "\" & $file)
                ;this is where you do what you need to do
            Endif
        EndIf
        If StringInStr(FileGetAttrib($current & "\" & $file), "D") And ($file <> "." Or $file <> "..") Then
            Search($current & "\" & $file, $searchQuery)
            
        EndIf
    WEnd
    FileClose($search)

EndFunc
Link to comment
Share on other sites

I tried copying the script that was entered above and i received the following error...

>"C:\Program Files\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "C:\Documents and Settings\blackey02\Desktop\New AutoIt v3 Script.au3" /autoit3dir "C:\Program Files\AutoIt3" /UserParams

>Running AU3Check params: from:C:\Program Files\AutoIt3\SciTE\au3check\

+>AU3Check ended.rc:0

>Running:(3.1.1.0):C:\Program Files\AutoIt3\autoit3.exe "C:\Documents and Settings\blackey02\Desktop\New AutoIt v3 Script.au3"

C:\Documents and Settings\blackey02\Desktop\New AutoIt v3 Script.au3 (5) : ==> Unable to open file, the maximum number of open files has been exceeded.:

Local $search = FileFindFirstFile($current & "\*.*")

C:\Documents and Settings\blackey02\Desktop\New AutoIt v3 Script.au3 (5) : ==> Error in expression.:

Local $search = FileFindFirstFile($current & "\*.*")

Local $search = ^ ERROR

+>AutoIT3.exe ended.rc:0

>Exit code: 0 Time: 0.539

Link to comment
Share on other sites

  • Developers

This means you have too many subdirectory levels.

This version doesn't have that issue:

; AutoIt Version: 3.0
; Language:       English
; Platform:       Win9x/NT/XP
; Author:         jos van der Zande
;
; Find files in directory and subdirectories and return it in an Array, all coded in Autoit3
; 
Dim $FILES
Dim $DIR="c:\winutil\autoit3\programs\test"  ; specify the directory to search
Dim $FILEMASK="*.au3"                        ; specify the filemask

$FILES = _GetFileList($DIR, $FILEMASK)
For $X = 0 To UBound($FILES)-1
   MsgBox(0,'test:' & $X,$FILES[$X])
Next 
Exit
;********************************************************************************
;Recursive search for filemask
;********************************************************************************

Func _GetFileList($T_DIR,$T_MASK)
   Dim $N_DIRNAMES[200000] ; max number of directories that can be scanned
   Local $N_DIRCOUNT = 0
   Local $N_FILE
   Local $N_SEARCH
   Local $N_TFILE
   Local $N_OFILE
   Local $T_FILENAMES
   Local $T_FILECOUNT
   Local $T_DIRCOUNT = 1
   ; remove the end \ If specified
   If StringRight($T_DIR,1) = "\" Then $T_DIR = StringTrimRight($T_DIR,1)
   $N_DIRNAMES[$T_DIRCOUNT] = $T_DIR
   ; Exit if base dir doesn't exists
   If Not FileExists($T_DIR) Then Return 0
   ; keep on looping until all directories are scanned
   While $T_DIRCOUNT > $N_DIRCOUNT
      $N_DIRCOUNT = $N_DIRCOUNT + 1
      ; find all subdirs in this directory and save them in a array
      $N_SEARCH = FileFindFirstFile($N_DIRNAMES[$N_DIRCOUNT] & "\*.*")  
      While 1
         $N_FILE = FileFindNextFile($N_SEARCH) 
         If @error Then ExitLoop
         ; skip these references
         If $N_FILE = "." Or $N_FILE = ".." Then ContinueLoop
         $N_TFILE = $N_DIRNAMES[$N_DIRCOUNT] & "\" & $N_FILE
         ; if Directory than add to the list of directories to be processed 
         If StringInStr(FileGetAttrib( $N_TFILE ),"D") > 0 Then
            $T_DIRCOUNT = $T_DIRCOUNT + 1
            $N_DIRNAMES[$T_DIRCOUNT] = $N_TFILE
         EndIf
      Wend
      FileClose($N_SEARCH)
      ; find all Files that mtach the MASK
      $N_SEARCH = FileFindFirstFile($N_DIRNAMES[$N_DIRCOUNT] & "\" & $T_MASK )  
      If $N_SEARCH = -1 Then ContinueLoop
      While 1
         $N_FILE = FileFindNextFile($N_SEARCH) 
         If @error Then ExitLoop
         ; skip these references
         If $N_FILE = "." Or $N_FILE = ".." Then ContinueLoop
         $N_TFILE = $N_DIRNAMES[$N_DIRCOUNT] & "\" & $N_FILE
         ; if Directory than add to the list of directories to be processed 
         If StringInStr(FileGetAttrib( $N_TFILE ),"D") = 0 Then
            $T_FILENAMES  = $T_FILENAMES & $N_TFILE & @CR
            $T_FILECOUNT = $T_FILECOUNT + 1
            ;MsgBox(0,'filecount ' & $T_FILECOUNT ,$N_TFILE)
         EndIf
      Wend
      FileClose($N_SEARCH)
   Wend
   $T_FILENAMES  = StringTrimRight($T_FILENAMES,1)
   $N_OFILE = StringSplit($T_FILENAMES,@CR)
   Return( $N_OFILE )
EndFunc   ;==>_GetFileList

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • Moderators

Worked like a charm!

what is the difference between release and beta that make the script work?

The beta has more functions and functionality than the release version. It's what is used to determine what's going to be in the next released version.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

  • 3 weeks later...
  • 1 month later...

Hi Jos,

it works famous. Thanks

In case to need only directories, I've made an enlargement to use your function with flag DIR_ONLY.

I hope you like that.

; AutoIt Version: 3.0
; Language:       English
; Platform:       Win9x/NT/XP
; Author:         jos van der Zande
;
; Find files in directory and subdirectories and return it in an Array, all coded in Autoit3
;
Dim $FILES
Dim $DIR="C:\Programme\autoit3\"  ; specify the directory to search
Dim $FILEMASK="n"                 ; specify the filemask ("n" for GetDirOnly)
$FILES = _GetFileList($DIR, $FILEMASK, 1)   ; _GetFileList($DIR, $FILEMASK [, Flag])  Flag GetFile(Default) = 0 , GetDirOnly = 1
For $X = 0 To UBound($FILES)-1
   MsgBox(0,'test:' & $X,$FILES[$X])
Next 
Exit
;********************************************************************************
;Recursive search for filemask
;********************************************************************************

Func _GetFileList($T_DIR,$T_MASK,$DIR_ONLY=0)
   Dim $N_DIRNAMES[200000] ; max number of directories that can be scanned
   Local $N_DIRCOUNT = 0
   Local $N_FILE
   Local $N_SEARCH
   Local $N_TFILE
   Local $N_OFILE
   Local $T_FILENAMES
   Local $T_FILECOUNT
   Local $T_DIRCOUNT = 1
   ; check Filemask \ to let File-Array empty by GetDirOnly
   If $T_MASK = "n" Then $T_MASK = "*.no"
   ; remove the end \ If specified
   If StringRight($T_DIR,1) = "\" Then $T_DIR = StringTrimRight($T_DIR,1)
   $N_DIRNAMES[$T_DIRCOUNT] = $T_DIR
   ; Exit if base dir doesn't exists
   If Not FileExists($T_DIR) Then Return 0
   ; keep on looping until all directories are scanned
   While $T_DIRCOUNT > $N_DIRCOUNT
      $N_DIRCOUNT = $N_DIRCOUNT + 1
      ; find all subdirs in this directory and save them in a array
      $N_SEARCH = FileFindFirstFile($N_DIRNAMES[$N_DIRCOUNT] & "\*.*") 
      While 1
         $N_FILE = FileFindNextFile($N_SEARCH)
         If @error Then ExitLoop
         ; skip these references
         If $N_FILE = "." Or $N_FILE = ".." Then ContinueLoop
         $N_TFILE = $N_DIRNAMES[$N_DIRCOUNT] & "\" & $N_FILE
         ; if Directory than add to the list of directories to be processed
         If StringInStr(FileGetAttrib( $N_TFILE ),"D") > 0 Then
            $T_DIRCOUNT = $T_DIRCOUNT + 1
            $N_DIRNAMES[$T_DIRCOUNT] = $N_TFILE
         EndIf
      Wend
      FileClose($N_SEARCH)      ; find all Files that mtach the MASK
      $N_SEARCH = FileFindFirstFile($N_DIRNAMES[$N_DIRCOUNT] & "\" & $T_MASK ) 
      If $N_SEARCH = -1 Then ContinueLoop
      While 1
         $N_FILE = FileFindNextFile($N_SEARCH)
         If @error Then ExitLoop
         ; skip these references
         If $N_FILE = "." Or $N_FILE = ".." Then ContinueLoop
         $N_TFILE = $N_DIRNAMES[$N_DIRCOUNT] & "\" & $N_FILE
         ; if Directory than add to the list of directories to be processed
         If StringInStr(FileGetAttrib( $N_TFILE ),"D") = 0 Then
            $T_FILENAMES  = $T_FILENAMES & $N_TFILE & @CR
            $T_FILECOUNT = $T_FILECOUNT + 1
            ;MsgBox(0,'filecount ' & $T_FILECOUNT ,$N_TFILE)
         EndIf
      Wend
      FileClose($N_SEARCH)
    Wend
    If $DIR_ONLY = 0 Then
      $T_FILENAMES  = StringTrimRight($T_FILENAMES,1)
      $N_OFILE = StringSplit($T_FILENAMES,@CR)
      Return( $N_OFILE )
    Else
      ReDim $N_DIRNAMES[$N_DIRCOUNT+1]
      $N_DIRNAMES[0] = $N_DIRCOUNT
      Return $N_DIRNAMES
    EndIf
EndFunc   ;==>_GetFileList
Edited by BugFix

Best Regards BugFix  

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...