Sign in to follow this  
Followers 0
birdofprey

Trying to read paths to files of a folder and of its subfolders to an array

11 posts in this topic

#1 ·  Posted (edited)

Something's wrong with my GetSubFolders() function. Even though the whole thing is fishy. I can't get rid of the feeling that there has to be a simpler way to do this.

#include <File.au3>
#include <Array.au3>

Dim $pathlist[1]
Global $pl[1] = [0]

$f = FileSelectFolder  ( "Choose a folder", "L:\E" , 2 )
;~ GetFiles ($f)
GetSubFolders ($f)
_ArrayDisplay ($pl, "final array")


Func GetFiles (ByRef $folder)
$filelist =_FileListToArray ( $folder , "*.mp3" , 1 )
If $filelist <> "" Then
    $pathlist = cnv2path ($folder, $filelist)
    Global $pl = _ArrayMerge ( $pl, $pathlist)
;~  MsgBox (0, "$pl", $pl)
EndIf
EndFunc

Func GetSubFolders (ByRef $folder)
$folderlist =_FileListToArray ( $folder , "*" , 2 )
If $folderlist = "" then ;no subfolders
    GetFiles ($folder)
Else ;there are subfolders - get it's subs and files
    $pathlistf = cnv2path ($folder, $folderlist)
    _ArrayDisplay ($pathlistf, $pathlist[0])
    For $p = 1 to $pathlistf[0]
        msgbox (0, $p, $pathlistf[$p])
        GetSubFolders ($pathlistf[$p])  ;<------- I get GetSubFolders($f) instead GetSubFolders($pathlist[$p]) I guess...
        _ArrayDisplay ($pathlistf[$p], $p)
    Next
EndIf
EndFunc

Func cnv2path(Byref $folder, ByRef $flist)
    For $p = 1 to $flist[0]
        ReDim $pathlist[$p + 1]
        $pathlist[$p] = $folder & "\" & $flist[$p]
;~      MsgBox (0, $p, $pathlist[$p])
    Next
        $pathlist[0] = UBound($pathlist) - 1
    Return $pathlist
EndFunc

Func _ArrayMerge (ByRef $array1, ByRef $array2 )
    If IsArray ($array1) then
        _ArrayDelete ( $array1, 0 )
        _ArrayDelete ( $array2, 0 )
        ReDim $array1[UBound($array1) + UBound($array2) ]
        For $x = 0 To UBound($array2) - 1
            $array1[UBound($array1) - UBound($array2) + $x] = $array2[$x]
        Next
        ReDim $array1 [UBound($array1) + 1]
        For $x = UBound($array1) - 1 To 1 step -1
            $array1[$x] = $array1[$x - 1]
        Next
    Else
        $array1 = $array2
    EndIf
    $array1[0] = UBound($array1) - 1
    ;~ _ArrayDisplay($array1, "test")
    Return $array1
EndFunc
Edited by birdofprey

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Ok, it wasn't simple but I figured out what the problem was. Well... at least partially. I initially thought that the variable isn't passed correctly or that Autoit doesn't like to call the functions inside the part where the function is declared. That wasn't true.

The _FileListToArray returns an empty array instead of a nothing in case there are no files or folders. And it has no @error level for not finding any folders.

I modified the code to (basically just changed the if criteria):

Func GetFiles (ByRef $folder)
$filelist =_FileListToArray ( $folder , "*.mp3" , 1 )
If UBound ($filelist) <> 1 ;<------------------------------------
    $pathlist = cnv2path ($folder, $filelist)
    Global $pl = _ArrayMerge ( $pl, $pathlist)
MsgBox (0, "$pl", $pl)
EndIf
EndFunc

Func GetSubFolders (ByRef $folder)
    MsgBox (0, "111", $folder)
$folderlist =_FileListToArray ( $folder , "*" , 2 )
_ArrayDisplay ($folderlist, "")
If UBound ($folderlist) = 1 Then ;no subfolders <--------------
    GetFiles ($folder)
Else ;there are subfolders - get it's subs and files
    Global $pathlistf = cnv2path ($folder, $folderlist)
    _ArrayDisplay ($pathlistf, $pathlist[0])
    For $p = 1 to $pathlistf[0]
        GetSubFolders ($pathlistf[$p])
    Next
EndIf
EndFunc

Problem is that AutoIt crashes after, I guess, trying to read the first subdirectory of the first directory in which it finds directories. :whistle:

Edited by birdofprey

Share this post


Link to post
Share on other sites

I havent read your script but AFAIK there is a top in numbers of times you can recursive a function....


Start here if you are new Valuater's AutoIT 1-2-3Looking for an UDF - Look hereDo you need to do it twice - Autoit

Share this post


Link to post
Share on other sites

I havent read your script but AFAIK there is a top in numbers of times you can recursive a function....

That sounds... great ! :shocked:

So, how do you read every file from every subdirectory of a directory to an array ? I can't believe no one needed such a function before...

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

THIS IS NOT MY SCRIPT !!!

i've found it @ this forum but I dont remember the username , I'll search and post it ...

it works PERFECT and is fast. I have used also some 'dos' based functions but they dont show the language (greek) fine ... so this is good and works fine:

call("subs",$startdir,$search,$x,$z,$q)

Func subs($startdir,$search,$x,$z,$q)         
if stringright($startdir,1)="\" then $startdir=stringleft($startdir,(stringlen($startdir)-1))
    
$search = FileFindFirstFile($startdir & "\*.*")   
If $search = -1 Then return -1              
While 1
    $y=$y+1
    $file = FileFindNextFile($search)               
    If @error Then                

  FileClose($search)              
  return                                    
Elseif  $file = "."  or $file = ".." Then       
  ContinueLoop                                              
ElseIf stringinstr(FileGetAttrib($startdir & "\" & $file),"D") then     
  subs($startdir & "\" & $file,$search,$x,$z,$q)        

    EndIf 
            
        $found=0
        
            
ConsoleWrite( $startdir & "\" & $file & @crlf )
WEnd

                    
                EndFunc

I had created one by myself but it stopped because of recursive limit

but this is ok ...

i have made a backup utility that is quite cool ....

it uses an .ini file and you give pairs of directories u want to synchronize. (u can use filenames, autocreate folders, export logfiles etc) ....

someday I will post it here. Now I am creating a server startup application

Edited by abarth

Share this post


Link to post
Share on other sites

This might help:

#include <Array.au3>
#include <File.au3>

Func _DirListToArray($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

AutoIt is simple, subtle, elegant. © AutoIt Team

Share this post


Link to post
Share on other sites

Func subs($startdir,$search,$x,$z,$q)         

[...]
                                    
ElseIf stringinstr(FileGetAttrib($startdir & "\" & $file),"D") then     
  subs($startdir & "\" & $file,$search,$x,$z,$q)        

[...]

EndFunc
Thank you abarth. It helped. I removed $x, $z, $q... made it output to an array instead of the console... and it works. I have no idea why but it works. I see a certain similarity here to my code... so the problem is not the recursive limit (if there's such a thing). But what's wrong with my script ??? Why does AutoIt crash ?

Share this post


Link to post
Share on other sites

Just a note on the recursion limits, here's an extract from the help file under FAQ's

"Maximum depth of recursive function calls: 384 levels"


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

This might help:

#include <Array.au3>
#include <File.au3>

Func _DirListToArray($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc
Wow. That's exactly what I tried to do myself. Your code is beautiful. It just fascinates me that... (well, I don't know how to explain this in a better way) there was a need for a $blist, but there is no need for a $clist and so on. I still don't get it completely :"> , but I'll work on that. Another thing that stopped me writing this before you is that I couldn't find the right place for that Return value. Thanks a lot ! :shocked: I learned a lot.

Share this post


Link to post
Share on other sites

Just a note on the recursion limits, here's an extract from the help file under FAQ's

"Maximum depth of recursive function calls: 384 levels"

Yeah, now that you mention this, it rings a bell... I read that a year ago or so. However, that wasn't the problem. And it only would be a problem if I had a folder with 384 subdirs...

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

This might help:

#include <Array.au3>
#include <File.au3>

Func _DirListToArray($sPath)
    Local $i, $j, $rlist[1]=[0], $blist, $alist=_FileListToArray ($sPath, '*', 2)
    If IsArray ($alist) Then
        For $i=1 To $alist [0]
            _ArrayAdd ($rlist, $sPath & "\" & $alist [$i])
            $blist = _DirListToArray ($sPath & "\" & $alist [$i])
            If $blist[0]>0 Then
                For $j=1 To $blist [0]
                    _ArrayAdd ($rlist, $blist [$j])
                Next
            EndIf
        Next
    EndIf
    $rlist [0] = UBound ($rlist) - 1
    Return $rlist
EndFunc
As I said, the code above is perfect: cause it does what I want it to do in the way I needed, thus it was easy to integrate this into the rest of my script. But I discovered now that it has a flaw:

For some reason when I try to read the "root" folder, I get stuck in a "E:\\"

Edit: Never mind, I only had to check the whether there is a trailing \ before calling this function and remove it if it's the case.

Edited by birdofprey

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