Jump to content
Sign in to follow this  
batfastad

showing file copy progress...

Recommended Posts

batfastad

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

Share this post


Link to post
Share on other sites
batfastad

Also to prove that it doesnt work, i put in a msg box, which only comes up after the file has finished copying

What 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+a

ctrl+c

change to the destination window

ctrl+v

then 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.

Thanks

Ben

Share this post


Link to post
Share on other sites
ezzetabi

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.

Share this post


Link to post
Share on other sites
ezzetabi

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.

_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 by ezzetabi

Share this post


Link to post
Share on other sites
MHz

Very nice, ezzetabi

Just tested here. :idiot:

Another good one for my collection Thanks.

Share this post


Link to post
Share on other sites
ezzetabi

There is no way to know, WHAT files are not been copied.

Should the udf returns a list of those?

Share this post


Link to post
Share on other sites
this-is-me

@ezzetabi, Please do give a listing (maybe return an array) of those files that had an error copying.


Who else would I be?

Share this post


Link to post
Share on other sites
ezzetabi

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.

Share this post


Link to post
Share on other sites
this-is-me

@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?

Share this post


Link to post
Share on other sites
ezzetabi

Done, but it was not a problem. Just keep the button pressed while moving the whell...

Share this post


Link to post
Share on other sites
this-is-me

I see now. Thanks.


Who else would I be?

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  

×