Jump to content
Sign in to follow this  
mikell

Display files sorted by size

Recommended Posts

mikell

Hello

Could't find this anywhere...

In a ListBox or Edit which displays a list of files, how to make this list sort them by size (biggest above, smallest below) ?

Many thanks to any helper

Share this post


Link to post
Share on other sites
DW1

Maybe there is a simpler way, but the way I would go about it is get all the files in an array and then get all the filesizes in an array with the filenames. Now we can just sort the array based on the filesize, then display the contents anywhere.

Something like this:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <array.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 600, 450)
$Edit1 = GUICtrlCreateEdit("", 300, 0, 300, 400)
GUICtrlSetData(-1, "")
$List1 = GUICtrlCreateList("", 0, 0, 300, 400, BitOR($WS_BORDER, $WS_VSCROLL)); Set default style with the exception of $LBS_SORT, which forces alphabetical sorting
$Bfolder = GUICtrlCreateButton("Select Folder To Read File In From", 0, 400, 600, 50)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Bfolder
            $SFolder = FileSelectFolder("Select Folder", "")
            If $SFolder <> '' Then
                If StringRight($SFolder, 1) <> '\' Then $SFolder &= '\'; Add trailing slash if it isn't there
                $AFiles = _FileSearch($SFolder & '*.*', 0, 0, 1, 0)
            Else
                Dim $AFiles[1]
                $AFiles[0] = 0
            EndIf
            If $AFiles[0] <> 0 Then
                Dim $ASize[$AFiles[0]][2]
                For $a = 1 To $AFiles[0]
                    $ASize[$a - 1][0] = FileGetSize($AFiles[$a])
                    $ASize[$a - 1][1] = $AFiles[$a]
                Next
                _ArraySort($ASize)

                ;For Edit
                $SEditString = ''
                For $a = 0 To UBound($ASize) - 1
                    $SEditString &= $ASize[$a][1]
                    If $a <> UBound($ASize) - 1 Then $SEditString &= @CRLF
                Next
                GUICtrlSetData($Edit1, $SEditString)

                ;For List
                $SListString = ''
                For $a = 0 To UBound($ASize) - 1
                    $SListString &= $ASize[$a][1]
                    If $a <> UBound($ASize) - 1 Then $SListString &= '|'
                Next
                GUICtrlSetData($list1, ''); Clear any old data
                GUICtrlSetData($List1, $SListString)
            EndIf
    EndSwitch
WEnd

; ---------File Search Functions----------

; _FileSearch( "Path and Mask", <$nOption>, <$cpusaver>, <$dirfilter>, <$filefilter>)
;
;----PARAMETERS-----
;$nOption -   <Optional (0 - normal, 1- recursive)>
;$cpusaver -  <Optional (0 - normal, 1 - CPU Friendly, but Slower)>
;$dirfilter - <Optional (0 - list directories, 1 - filter out directories)>
;$filefilter- <Optional (0 - list files, 1 - filter out files)>
;
;----RETURN-----
; Returns array. Either Array of files (full path) where...
; Array[0] is number of files.
; Array[0] = 0 if nothing found.
; EXAMPLE USAGE
;--------------------------------------------
;~ #include<array.au3>
;~ $a = _FileSearch("C:\*.*", 1, 0, 0, 0)
;~ _ArrayDisplay($a)
;--------------------------------------------
Func _FileSearch($szMask, $nOption = 0, $cpusaver = 0, $dirfilter = 0, $filefilter = 0)
    $szRoot = ""
    $hFile = 0
    $szBuffer = ""
    $szReturn = ""
    $szPathList = "*"
    Dim $aNULL[1]

    If Not StringInStr($szMask, "\") Then
        $szRoot = @ScriptDir & "\"
    Else
        While StringInStr($szMask, "\")
            $szRoot = $szRoot & StringLeft($szMask, StringInStr($szMask, "\"))
            $szMask = StringTrimLeft($szMask, StringInStr($szMask, "\"))
        WEnd
    EndIf
    If $nOption = 0 Then
        _FileSearchUtil($szRoot, $szMask, $szReturn, $cpusaver, $dirfilter, $filefilter)
    Else
        While 1
            $hFile = FileFindFirstFile($szRoot & "*.*")
            If $hFile >= 0 Then
                $szBuffer = FileFindNextFile($hFile)
                While Not @error
                    If $szBuffer <> "." And $szBuffer <> ".." And _
                            StringInStr(FileGetAttrib($szRoot & $szBuffer), "D") Then _
                            $szPathList = $szPathList & $szRoot & $szBuffer & "*"
                    $szBuffer = FileFindNextFile($hFile)
                WEnd
                FileClose($hFile)
            EndIf
            _FileSearchUtil($szRoot, $szMask, $szReturn, $cpusaver, $dirfilter, $filefilter)
            If $szPathList == "*" Then ExitLoop
            $szPathList = StringTrimLeft($szPathList, 1)
            $szRoot = StringLeft($szPathList, StringInStr($szPathList, "*") - 1) & "\"
            $szPathList = StringTrimLeft($szPathList, StringInStr($szPathList, "*") - 1)
        WEnd
    EndIf
    If $szReturn = "" Then
        $aNULL[0] = 0
        Return $aNULL
    Else
        Return StringSplit(StringTrimRight($szReturn, 1), "*")
    EndIf
EndFunc   ;==>_FileSearch

Func _FileSearchUtil(ByRef $ROOT, ByRef $MASK, ByRef $RETURN, $cpusaver, $dirfilter, $filefilter)
    $hFile = FileFindFirstFile($ROOT & $MASK)
    If $hFile >= 0 Then
        $szBuffer = FileFindNextFile($hFile)
        While Not @error
            If $cpusaver = 1 Then Sleep(1) ;OPTIONAL FOR CPU SAKE
            If $szBuffer <> "." And $szBuffer <> ".." Then
                If StringInStr(FileGetAttrib($ROOT & $szBuffer), "D") Then
                    If $dirfilter = 0 Then $RETURN = $RETURN & $ROOT & $szBuffer & "*"
                Else
                    If $filefilter = 0 Then $RETURN = $RETURN & $ROOT & $szBuffer & "*"
                EndIf
            EndIf
            $szBuffer = FileFindNextFile($hFile)
        WEnd
        FileClose($hFile)
    EndIf
EndFunc   ;==>_FileSearchUtil

Share this post


Link to post
Share on other sites
mikell

Thank you !

I can't see an easier solution than using your 2-dimensional array

I didn't know this _FileSearch function, isn't it possible to get the same result with the usual UDF _FileListToArray included in array.au3 File.au3 ? This should make the script simpler

Edited by mikell

Share this post


Link to post
Share on other sites
DW1

Yeah, you should be able to do the same thing with _FileListToArray, I have just been using that _FileSearch function for quite some time now. I like that I can make it recursive with a switch, and calm the CPU usage with a switch.

Share this post


Link to post
Share on other sites
mikell

I like this _FileSearch function

Til now I used this _FindFiles, I found it somewhere in the forum

#Include <Array.au3>

_FindFiles(@scriptdir, '*')

Func _FindFiles($sRoot, $sFile)
    Local $FileList
    $FileList = _FileListToArray($sRoot, $sFile, 2) 
    If Not @error Then
    _ArrayDisplay($FileList)
    ;For $i = 1 To $FileList[0]
    ;   FileWriteLine ($txt, $sRoot & '\' & $FileList[$i])  
        ;Next
   EndIf

    $FileList = _FileListToArray($sRoot, '*', 2)
    If Not @error Then
        For $i = 1 To $FileList[0]
            _FindFiles($sRoot & '\' & $FileList[$i], $sFile)    
        Next
    EndIf

EndFunc   ;==>_FindFiles

Recursive search too, and very easy to use

Share this post


Link to post
Share on other sites
omikron48

Here's a faster file search function:

;### SEARCH FUNCTION ###
;Returns array containing full path of matched files, with [0] containing the count of returned elements.
;
;PARAMETERS:
;
;$path        = start location of search
;
;$filter      = expression to use for file matching (e.g. *.txt)
;
;$depth       = folder depth to limit search
;               Default set to -1
;
;               Values:
;                   0  -> current folder only
;                   n  -> search up to n folders deep
;                   -1 -> search in all subfolders
;
;$directories = set to true if directories are to be included in the search results
;               Default set to True
;
;$files       = set to true if files are to be included in the search results
;               Default set to True
;
;RETURN VALUE:
;
;Success:   Array of files and folders matching the search parameter.
;           [0] contains the count of matched elements.
;           matched folders end with "\"
;
;Failure:   Returns 0.
;           Sets @error to:
;               1   -> $path does not exist.
;               2   -> No matches found.
;
Func _Search($path, $filter = "*", $depth = -1, $directories = True, $files = True)
    ;check directory exists
    If FileExists($path) Then
        ;add "\" to end of path value if needed
        If StringCompare(StringRight($path, 1), "\") <> 0 Then
            $path &= "\"
        EndIf
        Local $result = ""
        ;conduct search
        _SearchUtil($result, $path, $filter, $depth, $directories, $files)
        ;create return array
        If StringCompare(StringRight($result, 1), "|") == 0 Then
            $result = StringTrimRight($result, 1)
            $result = StringSplit($result, "|")
        Else
            $result = 0
            SetError(2, 0, 0)
        EndIf
        Return $result
    Else
        SetError(1, 0, 0)
    EndIf
EndFunc
Func _SearchUtil(ByRef $result, $path, $filter, $depth, $directories, $files)
    Local $search = FileFindFirstFile($path & $filter)
    Local $fname
    If $search <> -1 Then
        While 1
            $fname = FileFindNextFile($search)
            If @error == 1 Then
                ExitLoop
            EndIf
            ;skip processing if directory/file is not included in search results
            If @extended == 1 Then
                If Not $directories Then
                    ContinueLoop
                Else
                    $fname &= "\"
                EndIf
            Else
                If Not $files Then
                    ContinueLoop
                EndIf
            EndIf
            ;add file to results
            $result &= $path & $fname & "|"
        WEnd
        FileClose($search)
    EndIf
    ;process subdirectories if within depth parameter
    If $depth <> 0 Then
        $search = FileFindFirstFile($path & "*")
        While 1
            $fname = FileFindNextFile($search)
            If @error == 1 Then
                ExitLoop
            EndIf
            ;search subdirectory
            If @extended == 1 Then
                _SearchUtil($result, $path & $fname & "\", $filter, $depth - 1, $directories, $files)
            EndIf
        WEnd
        FileClose($search)
    EndIf
EndFunc
;### END SEARCH FUNCTION ###

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  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.