Jump to content
Sign in to follow this  

Recursive archiving script

Recommended Posts

Good Morning,

Long time watcher, first time poster! I've been writing a script to automate archiving machines for backup, but it's not quite working as expected and I can't work out where I'm going wrong.

The script uses recursion (I know I know).

The idea of the script is the user selects the root directory to archive. The script then copies all folders within that directory into an array, and calls itself on each folder in turn. It will recurse throught the folders until it reaches a branch with no further subfolders.

When there are no futher subfolders, the script will compress each file within that folder which does not already have a .zip extension into an archive file called directoryname.zip.

I have used runwait with an external program so that it does not try zipping multiple instances and grinding the computer to a standstill. I use zipgenius personally because it's free.

The problem I am having is recursing through the directory structure. After reaching a point where there are no more subfolders, the script displays the debug message to say there are no more folders found, but does not move onto compressing the contents of the current subfolder.

#Include <File.au3>
#Include <Array.au3>

; Script Start - Add your code below here
dim $rootdir = FileSelectFolder ("Select Root folder for Zip", "", 4)       ; select the root folder from which recursive zipping will start


Func ZipDir($dir)


MsgBox(64, "Directory", "Dir is: " & $dir)
$dirList=_FileListToArray($dir, "*", 2)
If @Error=1 Then
    MsgBox (0,"","Folder Not Found.")
        _ArrayDelete($dirList, 0)
        for $directory in $dirList

;MsgBox(64, "Directory", "Dir is: " & $dir)                             ; Debugging: ensure correct folder is selected
; Put all files from the root of the folder into an array
If @Error=4 Then
    ;MsgBox (0,"","No Files Found.")
    ;_ArrayDisplay($FileList,"$FileList")                                   ; Debugging: Display list of files in root folder

; remove .ZIP files from the array, these are not to be added to the archive
$sSearch = ".zip"
$noZips = 0
Do                                                                      ; loop through array until no more .zip files are found
    $iIndex = _ArraySearch($FileList, $sSearch, 0, 0, 0, 1)
    if @error Then
        ;MsgBox(0, "Not Found", '"' & $sSearch & '" was not found in the array.')
        $noZips = 1                                                     ; search cannot find any files with .zip and will exit loop
        ;MsgBox(0, "Found", '"' & $sSearch & '" was found in the array at position ' & $iIndex & ".")
        _ArrayDelete($FileList, $iIndex)                                ;search found file with .zip extension and removed it from the array
Until $noZips = 1
_ArrayDelete($FileList, 0)
;_ArrayDisplay($FileList,"$FileList")                                   ; Debugging: Display list of files in root folder after zips removed

$folders = StringSplit ($dir,"\")                                       ;find the name of the current working folder and strip out the path to generate a file name for the new zip
$folder = _ArrayPop($folders)

;MsgBox(64, "folder", "folder: " & $folder)

for $file in $FileList
runwait('zg -add "' & $folder & '.zip" C5 +"' & $file & '"')


Any assistance would be greatly appreciated! For anyone wanting to test the script themselves, I have attached it and ZG can be downloaded here: ZG download



Share this post

Link to post
Share on other sites


Welcome to the AutoIt forum. :)

The script uses recursion (I know I know)

Then why do it? :(

I try to avoid it like the plague - too easy to screw up and too hard to debug. So with very few apologies I admit to not having looked too hard at your code. ;)

To make up for that, here is a recursive folder finder which does not use recursion. It gives you a array of all the folders and subfolders in the path you set at the start - once you have it you can loop through it to zip up the contents of each one:

#include <Array.au3> ; Just needed for the ArrayDisplay - can be deleted when you are happy


Func _ZipFolders($sInitialPath)

    Local $asSearchFolderList[10] = [1], $asFoundFolderList[10] = [1], $sCurrentPath, $hSearch, $sName

    ; Ensure $sInitialPath has a trailing \
    If StringRight($sInitialPath, 1) <> "\" Then $sInitialPath = $sInitialPath & "\"
    ; Add path to list of folders to search
    $asSearchFolderList[1] = $sInitialPath
    ; Add path to list of folders found
    $asFoundFolderList[1] = StringTrimRight($sInitialPath, 1)

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

        ; Set path to search
        $sCurrentPath = $asSearchFolderList[$asSearchFolderList[0]]
        ; Reduce folder array count
        $asSearchFolderList[0] -= 1

        ; Get search handle
        $hSearch = FileFindFirstFile($sCurrentPath & "*")
        ; If folder empty move to next in list
        If $hSearch = -1 Then ContinueLoop

        ; Search folder
        While 1
            $sName = FileFindNextFile($hSearch)
            ; Check for end of folder
            If @error Then ExitLoop
            ; Check for subfolder and add to folder list
            If @extended Then
                ; Add to list of folders to search
                ; Increase list count
                $asSearchFolderList[0] += 1
                ; Double list size if too small (fewer ReDim needed)
                If UBound($asSearchFolderList) <= $asSearchFolderList[0] Then ReDim $asSearchFolderList[UBound($asSearchFolderList) * 2]
                ; Add value
                $asSearchFolderList[$asSearchFolderList[0]] = $sCurrentPath & $sName & "\"
                ; Add to list of folders found
                ; Increase list count
                $asFoundFolderList[0] += 1
                ; Double list size if too small (fewer ReDim needed)
                If UBound($asFoundFolderList) <= $asFoundFolderList[0] Then ReDim $asFoundFolderList[UBound($asFoundFolderList) * 2]
                ; Add value
                $asFoundFolderList[$asFoundFolderList[0]] = $sCurrentPath & $sName

        ; Close current search


    ReDim $asFoundFolderList[$asFoundFolderList[0] + 1] ; Get rid of any unused elements

    _ArrayDisplay($asFoundFolderList) ; Just for info
    For $i = 1 To $asFoundFolderList[0]
        ; Your zip code goes here


I hope it is all clear - please ask if not. :)


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:


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


Share this post

Link to post
Share on other sites

@Melba, thanks for your help. That seems to work perfectly! Just ironing out a few kinks and adding some functionality to remove backup and temp files before zipping

@Zedna, thanks for the suggestion, while the functionality is a lot more elegant than my way of removing the zip files from the file list, it seems a little OTT to add the full funtionality of _FileListToArrayEx() where I'm only really using it once. I'll bear it in mind for future projects though

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  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...