Jump to content
Sign in to follow this  
senthor

_FileListTreeToArray UDF

Recommended Posts

senthor

Hi!

After several questions, I created this UDF.

Comments:

; Name...........: _FileListTreeToArray
; Description ...: List all files from the wished directory with all files from all subfolders to an array.
; Syntax.........: _FileListTreeToArray($pFolder[, $tPath = 1[, $tType = 0]])
; Parameters ....: $pFolder - Path to the directory that has to be listed
;                 $tPath   - Optional: Path return type, "0" = absolute (default), "1" = relative
;                 $tType   - Optional: Search type, see "cmd.exe /K dir /?" at subpoint attributes
;                                Or see helptopic "FileGetAttrib"
;                          - Possible attributes: "RASHD"
;                                R: Readonly
;                                A: Archive
;                                S: System
;                                H: Hidden
;                                D: Directory
;                          - Combine with using different operators together, it's like a logical "AND" operator
;                                f.ex. "DR", will retrieve readonly directories
;                          - Exclude with a "-" before the operator, it's like a logical "AND NOT" operator
;                                f.ex. "D-R" will retrieve non readonly directories
;                          - Default: "", all files
;                 $tSort   - Optional: Sort results, see "cmd.exe /K dir /?" at subpoint order
;                          - Possible orders:
;                                N: Name, alphabetically
;                                S: Size, smaller files first
;                                E: Extension, alphabetically
;                                D: Date/Time, older files first
;                                G: Directories first
;                          - Not combineable
;                          - Turn over order by using a "-" before the operator
;                                f.ex. "-S" will retrieve big files first
;                          - Default: "N", names sorted alphabetically
; Return values .: Success  - Array with $array[0] = Number of files\folders returned, $array[n] = path of file/folder
;                  Failure: - Returns 0 and sets @error to:
;                                 0 if directory doen't exists
;                                 1 if Flags are wrong
;                                 2 if any other error occurs
;                             If @error = 2 then @extended will be set to:
;                                 1 if an OemToChar error occurs
;                                 2 if a Split error occurs
; Author ........: Jonas Neef, Thanks to bernd670 for Ascii help
; Remarks .......: Can take very long, needs CPU; Files with special chars may result in some other string, f.ex. "µ" -> "æ"
; Related .......: FileGetAttrib, FileSetAttrib, _FileListToArray
; Link ..........; http://www.gigahard.de.hm
; Example .......; No

Download: FileEx.au3

senthor

Edited by senthor

Share this post


Link to post
Share on other sites
clarinetmeister

Great script! Very helpful.

Share this post


Link to post
Share on other sites
zaini

good script,

it help me much for future use...

thanx :)

Edited by zaini

Share this post


Link to post
Share on other sites
KaFu

Nice job, but... I took a look into a lot of FileListTo() functions for my program SMF. What i found was that all functions using DOS commands lack the one or the other feature. One Problem (filenames with non-standard characters) you address using the OEM2ANSI dll call, which works in most circumstanced, another way I tested was

$foo = Run(@ComSpec, "", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
StdinWrite($foo, "chcp 1252" & @CRLF) ; change codepage for cmd.exe instance to 1252 (West European Latin)
StdinWrite($foo, "dir" & @CRLF)
StdinWrite($foo, "exit" & @CRLF) ; send exit command to trigger stdout
While 1
    $line &= StdoutRead($foo)
    If @error Then ExitLoop
Wend

but in most cases is not all, try to find a file with a

` character in the name and you'll see that it's translated into '

I don't know but guess, that this will happen with other foreign characters too.

The only solution I came up with finding all characters was a function using FileFindFirst() and FileFindNext(). To include sub-dir's you'll have to re-call the function for files found with the FileAttrib() D and put everything in an array.

Best Regards

Edited by KaFu

Share this post


Link to post
Share on other sites
uteotw

Most excellent, I needed something like this for a long time. Thanks a lot.

Now, I've found a small problem with it when I loop through folders very quickly my script (compiled or not) would "randomly" hang!

I tracked it down to this UDF and I've just made a couple tweaks to make it more reliable:

- added Local declaration to 3 variables, which is necessary when using Opt("MustDeclareVars", 1) in your scripts

- added ProcessWaitClose, not sure if it's really necessary but it doesn't hurt

- used DllOpen / DllClose

Func _FileListTreeToArray($pFolder, $tPath = 0, $tType = "", $tSort = "N")
    Local $wCheck = StringSplit(StringLeft($pFolder, 3), ":" )  ; <<< my tweak ... declared $wCheck
    If $wCheck[0] <> 2 and StringLeft($pFolder, 1) <> "\" then $pFolder = @WorkingDir & "\" & $pFolder
    If $wCheck[0] <> 2 and StringLeft($pFolder, 1) = "\" then $pFolder = @WorkingDir & $pFolder
    If StringRight($pFolder, 1) = "\" then $pFolder = StringTrimRight($pFolder, 1)
    If Not FileExists($pFolder) then Return Seterror(0, 0, 0)
    if $tPath > 1 OR $tPath < 0 then return Seterror(1, 0, 0)
    Local $wSort = StringReplace($tSort, "-", "")   ; <<< my tweak ... declared $wSort
    If StringLen($wSort) <> 1 or $wSort <> "N" and $wSort <> "S" and $wSort <> "E" and $wSort <> "D" and $wSort <> "G" and _
        $wSort <> "" then return Seterror(1, 0, 0)
    If Stringreplace(Stringreplace(Stringreplace( Stringreplace(Stringreplace(Stringreplace($tType, "-", ""), "H", ""), "S", _
        ""), "A", ""), "R", ""), "D", "") <> "" then return Seterror(1,0,0)
    local $uArray, $iStdout, $sTemp, $placeholder
    If $tType = "" Then
        $iStdout = Run(@comspec & ' /C cd ..\..\..\..\.. & dir "' & $pFolder & '" /A /B /O:' & $tSort & ' /S', @workingdir, _
            @SW_HIDE, 6)
    Else
        $iStdout = Run(@comspec & ' /C cd ..\..\..\..\.. & dir "' & $pFolder & '" /A:' & $tType & ' /B /O:' & $tSort & ' /S', _
            @workingdir, @SW_HIDE, 6)
    EndIF
    Local $line ; <<< my tweak ... declared $line
    While 1
        $line = StdoutRead($iStdout)
        If @error Then ExitLoop
        If $line <> "" then $sTemp &= $line
    Wend
    ProcessWaitClose($iStdout)  ; <<<< my tweak ... might be necessary in case of sub-processed?
    For $i = 0 To StringLen($sTemp)
        $placeholder &= "  "
    Next
    Local $dll = DllOpen("user32.dll")  ; <<<< my tweak ... dllopen
    $sTemp = DllCall($dll, "long", "OemToChar", "str", $sTemp, "str", $placeholder)
    DllClose($dll)  ; <<<< my tweak ... dllclose
    If Not Isarray($sTemp) or $sTemp[0] < 1 then return Seterror(2,1,0)
    $sTemp = $sTemp[2]
    $sTemp = StringReplace($sTemp, @crlf, @lf)
    $sTemp = StringReplace($sTemp, @cr, @lf)
    If StringRight($sTemp, 1) = @lf then $sTemp = StringTrimRight($sTemp, 1)
    If StringLeft($sTemp, 1) = @lf then $sTemp = StringTrimLeft($sTemp, 1)
    If Not StringInStr($sTemp, @lf) then
        If $sTemp = "" then
            local $return[1] = [0]
        Else
            local $return[2] = [1, $sTemp]
        EndIf
    Else
        local $return = StringSplit($sTemp, @lf)
    EndIF
    if not isarray($return) then
        Return Seterror(2,2,0)
    EndIF
    If $tPath = 1 Then
        For $dArray = 1 To $return[0] Step 1
            $return[$dArray] = StringReplace($return[$dArray], $pFolder & "\", "")
        Next
    EndIf
    return Seterror(0,0,$return)
EndFunc   ;==>_FileReadTreeInArray

Now, my scripts don't hang anymore :)

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  

×