MCornforth Posted April 16, 2010 Posted April 16, 2010 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.expandcollapse popup#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 EndFuncAny assistance would be greatly appreciated! For anyone wanting to test the script themselves, I have attached it and ZG can be downloaded here: ZG downloadMattZipMachineBackup.au3
Moderators Melba23 Posted April 16, 2010 Moderators Posted April 16, 2010 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: expandcollapse popup#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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
Zedna Posted April 16, 2010 Posted April 16, 2010 Also look at _FileListToArrayEx() in Examples forum. Resources UDF ResourcesEx UDF AutoIt Forum Search
MCornforth Posted April 20, 2010 Author Posted April 20, 2010 @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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now