Sign in to follow this  
Followers 0
MCornforth

Recursive archiving script

4 posts in this topic

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

ZipDir($rootdir)

Func ZipDir($dir)


FileChangeDir($dir)

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

;MsgBox(64, "Directory", "Dir is: " & $dir)                             ; Debugging: ensure correct folder is selected
; Put all files from the root of the folder into an array
$FileList=_FileListToArray($dir,"*",1)
If @Error=4 Then
    ;MsgBox (0,"","No Files Found.")
    Return
Else
    ;_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
    Else
        ;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
    EndIf
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 & '"')
Next
EndIf

EndFunc

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

Matt

ZipMachineBackup.au3

Share this post


Link to post
Share on other sites



MCornforth,

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

_ZipFolders("Your_Initial_Path")

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
            EndIf
        WEnd

        ; Close current search
        FileClose($hSearch)

    WEnd

    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
        
    Next

EndFunc

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

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______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

 

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  
Followers 0