batfastad Posted January 4, 2005 Posted January 4, 2005 Hi In my AutoIt script I have a DirCopy function which is used for a backup to a firewire external hard drive. I have a Splash window telling the user that the backup is in progress. Then once it's finished the device is ejected from the system by opening the 'Eject/unplug hardware box' and sending keystrokes to stop the correct device. Though the backup copies 90GB of data (and growing) so I'd like somehow to be able to show how many MB/GB of data has been copied. The only way I can think to do this is to somehow get the directory size of the source folder, and get the directory size of the destination folder, then work out a percentage figure. Then loop it so I update the figure every 5 seconds or so. Ideally I'd like to display both the number of MB copied as well as the total And the number of files copied as well as the total Is it possible to get the size of a directory, and the number of files inside a directory within AutoIt? I can't find any functions to help. I know that FileGetSize ( "filename" ) doesn't work on directories according to the AutoIt manual. I also realise I may have to do some maths to convert the returned size into a proper figure in GB rather than bytes. I just think it would be a great feature to have. I'll then also do some kind of progress bar. Any ideas? Thanks Batfastad
CyberSlug Posted January 4, 2005 Posted January 4, 2005 Latest beta version of AutoIt has a function DirGetrSizehttp://www.autoitscript.com/autoit3/files/beta/autoit/ Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
batfastad Posted January 4, 2005 Author Posted January 4, 2005 Also to prove that it doesnt work, i put in a msg box, which only comes up after the file has finished copyingWhat i have done in the past is to open explorer windows for the source and destination folders and send the keystrokes between the windows...ctrl+actrl+cchange to the destination windowctrl+vthen you get the built-in windows copy dialog box.Though I don't like doing it that way.I might take a look at that function and see if it's possible to do that.ThanksBen
ezzetabi Posted January 4, 2005 Posted January 4, 2005 The only way is using a _FileSearch UDF, it returns an array with all files names you need to copy. Sort that array in order of string lenght from shortest to longest path. Get the directory size and copy the files or make the folders one per one and every time add the filesize to the completed value, show a progress bar with the result of Directory size/completed.
ezzetabi Posted January 4, 2005 Posted January 4, 2005 (edited) I made a easy implementation of what I said. It may be probably improved, don't be fooled the lenghty code. The longest part is the well know _FileSearch and the _QuickSort functions. expandcollapse popup_CopyDirWithProgress('D:\Autoit3Scripts', 'D:\Autoit3Scripts\test') Exit Func _CopyDirWithProgress($sOriginalDir, $sDestDir) ;$sOriginalDir and $sDestDir are quite selfexplanatory... ;This func returns: ; -1 in case of critical error, bad original (@error = 1) or destination (@error = 2) dir ; '' (empty string) if everything went all right ; ; 'list|list|list' list of uncopied files, original full paths separed by pipes '|' ; @error is also set to 3 If StringRight($sOriginalDir, 1) <> '\' Then $sOriginalDir = $sOriginalDir & '\' If StringRight($sDestDir, 1) <> '\' Then $sDestDir = $sDestDir & '\' ProgressOn('Copying...', 'Making list of files...', '', -1, -1, 18) Local $aFileList = _FileSearch($sOriginalDir) If $aFileList[0] = 0 Then ProgressOff() SetError(1) Return -1 EndIf If FileExists($sDestDir) Then If Not StringInStr(FileGetAttrib($sDestDir), 'd') Then ProgressOff() SetError(2) Return -1 EndIf Else DirCreate($sDestDir) If Not FileExists($sDestDir) Then ProgressOff() SetError(2) Return -1 EndIf EndIf Local $iDirSize, $iCopiedSize = 0, $fProgress = 0 Local $c, $FileName, $iOutPut = '' Local $Sl = StringLen($sOriginalDir) _Quick_Sort($aFileList, 1, $aFileList[0]) $iDirSize = Int(DirGetSize ($sOriginalDir) / 1024) ProgressSet(Int($fProgress * 100), $aFileList[$c], 'Coping file:') For $c = 1 To $aFileList[0] $FileName = StringTrimLeft($aFileList[$c], $Sl) If StringInStr(FileGetAttrib($aFileList[$c]), 'd') Then DirCreate($sDestDir & $FileName) Else ProgressSet(Int($fProgress * 100), $aFileList[$c] & @lf & 'Total Kbytes: ' & $iDirSize & @lf & 'Done Kbytes: ' & $iCopiedSize) If Not FileCopy($aFileList[$c], $sDestDir & $FileName, 1) Then $iOutPut = $iOutPut & '|' & $aFileList[$c] EndIf $iCopiedSize = $iCopiedSize + Int(FileGetSize($aFileList[$c]) / 1024) $fProgress = $iCopiedSize / $iDirSize EndIf Next ProgressOff() If $iOutPut <> '' Then SetError(3) Return $iOutPut EndFunc ;==>_CopyDirWithProgress Func _FileSearch($sIstr, $bSF = 1) ; $bSF = 1 means looking in subfolders ; $sSF = 0 means looking only in the current folder. ; An array is returned with the full path of all files found. The pos [0] keeps the number of elements. Local $sIstr, $bSF, $sCriteria, $sBuffer, $iH, $iH2, $sCS, $sCF, $sCF2, $sCP, $sFP, $sOutPut = '', $aNull[1] $sCP = StringLeft($sIstr, StringInStr($sIstr, '\', 0, -1)) If $sCP = '' Then $sCP = @WorkingDir & '\' $sCriteria = StringTrimLeft($sIstr, StringInStr($sIstr, '\', 0, -1)) If $sCriteria = '' Then $sCriteria = '*.*' ;To begin we seek in the starting path. $sCS = FileFindFirstFile($sCP & $sCriteria) While $sCS <> - 1 $sCF = FileFindNextFile($sCS) If @error Then FileClose($sCS) ExitLoop EndIf If $sCF = '.' Or $sCF = '..' Then ContinueLoop $sOutPut = $sOutPut & $sCP & $sCF & @LF Wend ;And after, if needed, in the rest of the folders. If $bSF = 1 Then $sBuffer = @CR & $sCP & '*' & @LF;The buffer is set for keeping the given path plus a *. Do $sCS = StringTrimLeft(StringLeft($sBuffer, StringInStr($sBuffer, @LF, 0, 1) - 1), 1);current search. $sCP = StringLeft($sCS, StringInStr($sCS, '\', 0, -1));Current search path. $iH = FileFindFirstFile($sCS) While $iH <> - 1 $sCF = FileFindNextFile($iH) If @error Then FileClose($iH) ExitLoop EndIf If $sCF = '.' Or $sCF = '..' Then ContinueLoop If StringInStr(FileGetAttrib($sCP & $sCF), 'd') Then $sBuffer = @CR & $sCP & $sCF & '\*' & @LF & $sBuffer;Every folder found is added in the begin of buffer $sFP = $sCP & $sCF & '\'; for future searches $iH2 = FileFindFirstFile($sFP & $sCriteria); and checked with the criteria. While $iH2 <> - 1 $sCF2 = FileFindNextFile($iH2) If @error Then FileClose($iH2) ExitLoop EndIf If $sCF2 = '.' Or $sCF2 = '..' Then ContinueLoop $sOutPut = $sOutPut & $sFP & $sCF2 & @LF;Found items are put in the Output. Wend EndIf Wend $sBuffer = StringReplace($sBuffer, @CR & $sCS & @LF, '') Until $sBuffer = '' EndIf If $sOutPut = '' Then $aNull[0] = 0 Return $aNull Else Return StringSplit(StringTrimRight($sOutPut, 1), @LF) EndIf EndFunc ;==>_FileSearch Func _Quick_Sort(ByRef $SortArray, $First, $Last);Larry code Dim $Low, $High Dim $Temp, $List_Separator $Low = $First $High = $Last $List_Separator = StringLen($SortArray[ ($First + $Last) / 2]) Do While (StringLen($SortArray[$Low]) < $List_Separator) $Low = $Low + 1 Wend While (StringLen($SortArray[$High]) > $List_Separator) $High = $High - 1 Wend If ($Low <= $High) Then $Temp = $SortArray[$Low] $SortArray[$Low] = $SortArray[$High] $SortArray[$High] = $Temp $Low = $Low + 1 $High = $High - 1 EndIf Until $Low > $High If ($First < $High) Then _Quick_Sort($SortArray, $First, $High) If ($Low < $Last) Then _Quick_Sort($SortArray, $Low, $Last) EndFunc ;==>_Quick_Sort Edited January 4, 2005 by ezzetabi
Doxie Posted January 4, 2005 Posted January 4, 2005 Latest beta version of AutoIt has a function DirGetrSizehttp://www.autoitscript.com/autoit3/files/beta/autoit/<{POST_SNAPBACK}>Finally, you guys have no idea how much time this will save for me... Were ever i lay my script is my home...
MHz Posted January 4, 2005 Posted January 4, 2005 Very nice, ezzetabi Just tested here. Another good one for my collection Thanks.
ezzetabi Posted January 4, 2005 Posted January 4, 2005 There is no way to know, WHAT files are not been copied. Should the udf returns a list of those?
this-is-me Posted January 4, 2005 Posted January 4, 2005 @ezzetabi, Please do give a listing (maybe return an array) of those files that had an error copying. Who else would I be?
ezzetabi Posted January 4, 2005 Posted January 4, 2005 I prefere avoid returing an array, usually you'll have not errors... As is it returns a string separed by '|' pipes. Ready to StringSplit if needed.
this-is-me Posted January 4, 2005 Posted January 4, 2005 @ezzetabi, It seems that the codebox that you are now fond of is hard to copy from and keep the correct formatting. Please revert to regulat code for copying. Who else would I be?
ezzetabi Posted January 4, 2005 Posted January 4, 2005 Done, but it was not a problem. Just keep the button pressed while moving the whell...
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