Jump to content

Possible to read files in a directory 3 or 4 folders down?


Recommended Posts

I have another post about my idea to make a file name correction program. There is already one made but not I need a faster way to do what I wanna do. The program works great and it can take 01-Rob-Zombie-Living-Dead-Girl.mp3 and change it to Living Dead Girl.mp3 (which is what I want) but the script has to be in the folder with the mp3's in order for them to be changed. My files are in this structure:

Music folder ->Artist->CD Name->Actualfile.mp3

is there any way to make autoit read a few undefined files deep instead of just in the folder its in? I was thinking something something like:

Script here->*(wildcard)->*(wildcard)->*.mp3

Hoping that autoit would look a few folders down for the file but my attempts have failed.

Is this possible? or something like it?

Link to comment
Share on other sites

  • Moderators

RAMMRODD,

Try searching for "+recursive +file +search". There are many scripts on the forums which will delve deep into your folder structure.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

xZZTx has what I need. Sweet!

$Dir = @ScriptDir
$Dr1 = $Dir
$Dr2 = 0
dim $Dr[100]
$A = FileFindFirstFile("*.*")
while 1
$B = FileFindNextFile($A)
$C = StringSplit(FileGetLongName($B,1),".")
If @error = 0 Then
If $C[0] >= 2 Then
If $C[2] = "mp3"Then                               ;I put this in but its still adding .txt and .au3
      FileWriteLine("text.zzt",$Dir&"\"&$B)
  Else         
      msgbox(1,"nothing",$b)
      $Dr[$Dr[0]] = $Dr3&"\"&$B

   
EndIf
EndIf
EndIf
    If $C[0] = 1 And $B = Not "" Then
        If $Dr2 = 1 Then
            $Dr[0] += 1
        Else
        $Dr3 = $Dir
        $Dr2 = 1
        $Dir = $Dir&"\"&$B
        EndIf
    EndIf
    If $B = "" Then
        $Dr2 = 0
        If $Dir = $Dr1 Then
            If $Dr[0] = Not 0 Then
                $Dir = $Dr[$Dr[0]]
                $Dr[0] -= 1
                $Dr2 = 0
            Else
            ExitLoop
            EndIf
        EndIf
        $A = FileFindFirstFile($Dir&"\*.*")
        $Dr1 = $Dir
        $B = ""
    EndIf
WEnd

I commented part that I changed. I thought changing the original to just if *function*= "mp3" then write to file, it would just copy mp3 but it does all still. Any info on why?

Edited by RAMMRODD
Link to comment
Share on other sites

  • Moderators

RAMMRODD,

With apologies in advance to xZZTx, I have severe reservations over the utility of code you posted.

My main concern is that I see a FileFindFirstFile function in a loop with no corresponding CloseFile. From the Help file for FileFindFirstFile:

"When you have finished searching with the FileFind... functions you must call FileClose() to release the search handle."

Each process is limited to 512 handles, so I could see this code very rapidly running out of handles. My own music folder has 777 folders and subfolders, so this script would crash for sure if I used it to list my mp3s. :(

Given the above, I have no real inclination to debug this script. But you might be interested in these 2 versions of my current recursive file/folder finder. I have written them as formal include files, so just save them to your working folder and put #include"file-name" at the top of your script to use the function. I hope the instructions are self-explanatory and I have commented liberally so you should be able to follow what is going on.

The first uses recursion - which as a hobbyist coder does not concern me at all, although professionals throw their hands up in horror. :(

#include-once

; #FUNCTION# ====================================================================================================================
; Name...........:_FileListToArray_Rec
; Description ...: Lists files and\or folders in a specified path with optional recursion. Compatible with_FileListToArray syntax
; Syntax.........:_FileListToArray_Rec($sPath[, $sInclude_List = "*"[, $iReturn = 0[, $iRecur = 0[, $sExclude_List = ""[, $iFullPath = 0]]]]])
; Parameters ....: $sPath   - Initial path used to generate filelist
;                  $sInclude_List - Optional: the filter for included results (default is "*"). Multiple filters must be separated by ";"
;                  $iReturn   - Optional: specifies whether to return files, folders or both
;                  |$iReturn=0 (Default) Return both files and folders
;                  |$iReturn=1 Return files only
;                  |$iReturn=2 Return folders only
;                  $iRecur  - Optional: specifies whether to search in subfolders
;                  |$iRecur=0 (Default) Do not search in subfolders
;                  |$iRecur=1 Search in subfolders
;                  $sExclude_List - Optional: the filter for excluded results (default is ""). Multiple filters must be separated by ";"
;                  $iFullPath  - Optional: specifies path of result string
;                  |$iFullPath=0 (Default) Initial path not included
;                  |$iFullPath=1 Initial path included
;                  |$iFullPath=2 File/folder name only
; Requirement(s).: v3.3.1.1 or higher
; Return values .: Success:  One-dimensional array made up as follows:
;                  |$array[0] = Number of Files\Folders returned
;                  |$array[1] = 1st File\Folder
;                  |$array[2] = 2nd File\Folder
;                  |...
;                  |$array[n] = nth File\Folder
;                   Failure: Null string and @error set:
;                  |1 = Path not found or invalid
;                  |2 = Invalid $sInclude_List
;                  |3 = Invalid $iReturn
;                  |4 = Invalid $iRecur
;                  |5 = Invalid $sExclude_List
;                  |6 = Invalid $iFullPath
;                  |7 = No file/folder found
; Author ........: Melba23 using SRE code from forums
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func _FileListToArray_Rec($sPath, $sInclude_List = "*", $iReturn = 0, $iRecur = 0, $sExclude_List = "", $iFullPath = 0)

    Local $asReturnList[1] = [0], $sInitialPath, $sInclude_List_Mask, $sExclude_List_Mask

    ; Check valid path
    If Not FileExists($sPath) Then Return SetError(1, 1, "")
    ; Ensure trailing \
    If StringRight($sPath, 1) <> "\" Then $sPath = $sPath & "\"
    ; Set value for original path
    $sInitialPath = $sPath
    ; Determine Filter mask for SRE check
    If StringRegExp($sInclude_List, '\\|/|:|\"|\<|\>|\|') Then Return SetError(2, 2, "") ; Check if invalid characters within $sInclude_List
    $sInclude_List = StringReplace(StringStripWS(StringRegExpReplace($sInclude_List, '\s*;\s*', ';'), 3), ';', '|') ; Strip $sInclude_List of WS and insert |
    $sInclude_List_Mask = '(?i)^' & StringReplace(StringReplace(StringReplace($sInclude_List, '.', '\.'), '*', '.*'), '?', '.') & "\z" ; Convert $sInclude_List to SRE pattern
    ; Determine Exclude mask for SRE check
    If $sExclude_List = "" Then
        $sExclude_List_Mask = ':' ; Set unmatchable mask
    Else
        If StringRegExp($sExclude_List, '\\|/|:|\"|\<|\>|\|') Then Return SetError(5, 5, "") ; Check if invalid characters within $sExclude_List
        $sExclude_List = StringReplace(StringStripWS(StringRegExpReplace($sExclude_List, '\s*;\s*', ';'), 3), ';', '|') ; Strip $sExclude_List of WS and insert |
        $sExclude_List_Mask = '(?i)^' & StringReplace(StringReplace(StringReplace($sExclude_List, '.', '\.'), '*', '.*'), '?', '.') & "\z" ; Convert $sExclude_List to SRE pattern
    EndIf
    ; Verify other parameter values
    If Not ($iReturn = 0 Or $iReturn = 1 Or $iReturn = 2) Then Return SetError(3, 3, "")
    If Not ($iRecur = 0 Or $iRecur = 1) Then Return SetError(4, 4, "")
    If Not ($iFullPath = 0 Or $iFullPath = 1 Or $iFullPath = 2) Then Return SetError(6, 6, "")

    ; Search - $sRelativePath = ""
    _FLTA_Rec_Search($sPath, $sInitialPath, $sInclude_List_Mask, $iReturn, $iRecur, $sExclude_List_Mask, $iFullPath, $asReturnList)

    ; Check if array filled
    If $asReturnList[0] = 0 Then Return SetError(7, 7, "")
    ; Remove unused array elements from last ReDim
    ReDim $asReturnList[$asReturnList[0] + 1]

    Return $asReturnList

EndFunc   ;==>_FileListToArray_Rec

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _FLTA_Rec_Search
; Description ...: Searches folder for files and then optionally searches recursively in subfolders
; Syntax.........: _FLTA_Rec_Search($sCurrentPath, $sInitialPath, $sInclude_List, $iReturn, $iRecur, $sExclude_List, $sFullPath, ByRef $asReturnList)
; Parameters ....: $sCurrentPath - Current path to search
;                  $sInitialPath - Initial path used to generate filelist as set in_FileListToArray_Rec
;                  $sInclude_List_Mask - As set in_FileListToArray_Rec
;                  $iReturn - As set in_FileListToArray_Rec
;                  $iRecur - As set in_FileListToArray_Rec
;                  $sExclude_List_Mask - As set in_FileListToArray_Rec
;                  $iFullPath - As set in_FileListToArray_Rec
;                  $asReturnList - Array containing found files/folders
; Return values .: None
; Author ........: Melba23 based on _FileListToArray by SolidSnake with SRE code from forums
; Modified.......:
; Remarks .......: This function is used internally by_FileListToArray_Rec.
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func _FLTA_Rec_Search($sCurrentPath, $sInitialPath, $sInclude_List_Mask, $iReturn, $iRecur, $sExclude_List_Mask, $iFullPath, ByRef $asReturnList)

    Local $hSearch, $sName, $fFolder, $sReturnPath = ""

    ; Search folder
    $hSearch = FileFindFirstFile($sCurrentPath & "*")
    If $hSearch = 0 Then Return ; Folder empty
    ; Set path to add
    Switch $iFullPath
        Case 0 ; Initial path not included
            $sReturnPath = StringReplace($sCurrentPath, $sInitialPath, "")
        Case 1 ; Initial path included
            $sReturnPath = $sCurrentPath
        ; Case 2 ; Name only so leave as ""
    EndSwitch
    While 1
        $sName = FileFindNextFile($hSearch)
        $fFolder = @extended ; @extended set if $sName is folder in 3.3.1.1 +
        If @error Then ExitLoop ; End of folder
        ; Check file/folder type against required return value and file/folder name against Include/Exclude masks
        If $fFolder + $iReturn <> 2 And StringRegExp($sName, $sInclude_List_Mask) And Not StringRegExp($sName, $sExclude_List_Mask) Then
            ; Increase item count
            $asReturnList[0] += 1
            ; Double array size if too small (fewer ReDim needed)
            If UBound($asReturnList) <= $asReturnList[0] Then ReDim $asReturnList[UBound($asReturnList) * 2]
            ; Add required path to file/folder name and add to array
            $asReturnList[$asReturnList[0]] = $sReturnPath & $sName
        EndIf
        ; If recursive then search folder
        If $fFolder And $iRecur Then _FLTA_Rec_Search($sCurrentPath & $sName & "\", $sInitialPath, $sInclude_List_Mask, $iReturn, $iRecur, $sExclude_List_Mask, $iFullPath, $asReturnList)
    WEnd
    FileClose($hSearch)

EndFunc   ;==>_FLTA_Rec_Search

The second uses a folder stack, which is how "real" programmers do it >_< . It is very slightly faster, but does return the files/folders in a slightly mixed up order rather then nicely arranged:

; #FUNCTION# ====================================================================================================================
; Name...........: _FileListToArray_Stack
; Description ...: Lists files and\or folders in a specified path with optional recursion.  Compatible with existing _FileListToArray syntax
; Syntax.........: _FileListToArray_Stack($sPath[, $sInclude_List = "*"[, $iReturn = 0[, $fRecur = 0[, $sExclude_List = ""[, $iFullPath = 0]]]]])
; Parameters ....: $sPath   - Initial path used to generate filelist
;                  $sInclude_List - Optional: the filter for included results (default is "*"). Multiple filters must be separated by ";"
;                  $iReturn   - Optional: specifies whether to return files, folders or both
;                  |$iReturn=0 (Default) Return both files and folders
;                  |$iReturn=1 Return files only
;                  |$iReturn=2 Return folders only
;                  $fRecur  - Optional: specifies whether to search in subfolders
;                  |$fRecur=0 (Default) Do not search in subfolders
;                  |$fRecur=1 Search in subfolders
;                  $sExclude_List - Optional: the filter for excluded results (default is ""). Multiple filters must be separated by ";"
;                  $iFullPath  - Optional: specifies path of result string
;                  |$iFullPath=0 (Default) Initial path not included
;                  |$iFullPath=1 Initial path included
;                  |$iFullPath=2 File/folder name only
; Requirement(s).: v3.3.1.1 or higher
; Return values .: Success:  One-dimensional array made up as follows:
;                  |$array[0] = Number of Files\Folders returned
;                  |$array[1] = 1st File\Folder
;                  |$array[2] = 2nd File\Folder
;                  |...
;                  |$array[n] = nth File\Folder
;                   Failure: Null string and @error set:
;                  |1 = Path not found or invalid
;                  |2 = Invalid $sInclude_List
;                  |3 = Invalid $iReturn
;                  |4 = Invalid $fRecur
;                  |5 = Invalid $sExclude_List
;                  |6 = Invalid $iFullPath
;                  |7 = No file/folder found
; Author ........: Melba23 using SRE code from forums
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; ===============================================================================================================================
Func _FileListToArray_Stack($sInitialPath, $sInclude_List = "*", $iReturn = 0, $fRecur = 0, $sExclude_List = "", $iFullPath = 0)

    Local $asReturnList[1] = [0], $asFolderList[3] = [1], $sInclude_List_Mask, $sExclude_List_Mask
    Local $sCurrentPath, $hSearch, $sReturnPath = "", $sName, $fFolder

    ; Check valid path
    If Not FileExists($sInitialPath) Then Return SetError(1, 1, "")
    ; Ensure trailing \
    If StringRight($sInitialPath, 1) <> "\" Then $sInitialPath = $sInitialPath & "\"
    ; Add path to folder list
    $asFolderList[1] = $sInitialPath

    ; Determine Filter mask for SRE check
    If StringRegExp($sInclude_List, '\\|/|:|\"|\<|\>|\|') Then Return SetError(2, 2, "") ; Check if invalid characters within $sInclude_List
    $sInclude_List = StringReplace(StringStripWS(StringRegExpReplace($sInclude_List, '\s*;\s*', ';'), 3), ';', '|') ; Strip $sInclude_List of WS and insert |
    $sInclude_List_Mask = '(?i)' & StringReplace(StringReplace(StringReplace($sInclude_List, '.', '\.'), '*', '.*'), '?', '.') & "\z" ; Convert $sInclude_List to SRE pattern

    ; Determine Exclude mask for SRE check
    If $sExclude_List = "" Then
        $sExclude_List_Mask = ':' ; Set unmatchable mask
    Else
        If StringRegExp($sExclude_List, '\\|/|:|\"|\<|\>|\|') Then Return SetError(5, 5, "") ; Check if invalid characters within $sExclude_List
        $sExclude_List = StringReplace(StringStripWS(StringRegExpReplace($sExclude_List, '\s*;\s*', ';'), 3), ';', '|') ; Strip $sExclude_List of WS and insert |
        $sExclude_List_Mask = '(?i)' & StringReplace(StringReplace(StringReplace($sExclude_List, '.', '\.'), '*', '.*'), '?', '.') & "\z" ; Convert $sExclude_List to SRE pattern
    EndIf

    ; Verify other parameter values
    If Not ($iReturn = 0 Or $iReturn = 1 Or $iReturn = 2) Then Return SetError(3, 3, "")
    If Not ($fRecur = 0 Or $fRecur = 1) Then Return SetError(4, 4, "")
    If Not ($iFullPath = 0 Or $iFullPath = 1 Or $iFullPath = 2) Then Return SetError(6, 6, "")

    ; Search in listed folders
    While $asFolderList[0] > 0

        ; Set path to search
        $sCurrentPath = $asFolderList[$asFolderList[0]]
        ; Reduce folder array count
        $asFolderList[0] -= 1
        ; Get search handle
        $hSearch = FileFindFirstFile($sCurrentPath & "*")
        ; If folder empty move to next in list
        If $hSearch = -1 Then ContinueLoop

        ; Determine path to add to file/folder name
        Switch $iFullPath
            Case 0 ; Initial path not included
                $sReturnPath = StringReplace($sCurrentPath, $sInitialPath, "")
            Case 1 ; Initial path included
                $sReturnPath = $sCurrentPath
            ; Case 2 ; Name only so leave as ""
        EndSwitch

        ; Search folder
        While 1
            $sName = FileFindNextFile($hSearch)
            ; Check for end of folder
            If @error Then ExitLoop
            ; Check for subfolder - @extended set in 3.3.1.1 +
            $fFolder = @extended

            ; If recursive search, add subfolder to folder list
            If $fRecur And $fFolder Then
                ; Increase folder array count
                $asFolderList[0] += 1
                ; Double folder array size if too small (fewer ReDim needed)
                If UBound($asFolderList) <= $asFolderList[0] + 1 Then ReDim $asFolderList[UBound($asFolderList) * 2]
                ; Add subfolder to list
                $asFolderList[$asFolderList[0]] = $sCurrentPath & $sName & "\"
            EndIf

            ; Check file/folder type against required return value and file/folder name against Include/Exclude masks
            If $fFolder + $iReturn <> 2 And StringRegExp($sName, $sInclude_List_Mask) And Not StringRegExp($sName, $sExclude_List_Mask) Then
                ; Increase return array count
                $asReturnList[0] += 1
                ; Double return array size if too small (fewer ReDim needed)
                If UBound($asReturnList) <= $asReturnList[0] Then ReDim $asReturnList[UBound($asReturnList) * 2]
                ; Add required path to file/folder name and add to array
                $asReturnList[$asReturnList[0]] = $sReturnPath & $sName
            EndIf
        WEnd

        ; Close current search
        FileClose($hSearch)

    WEnd

    ; Check if any file/folders to return
    If $asReturnList[0] = 0 Then Return SetError(7, 7, "")
    ; Remove unused return array elements from last ReDim
    ReDim $asReturnList[$asReturnList[0] + 1]

    Return $asReturnList

EndFunc   ;==>_FileListToArray_Stack

Try them both and see which you prefer. Any comments welcome. Feel free to use all or any of the code in your own scripts.

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

  • 2 months later...

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