Jump to content

German Multi-file copy with progressbar


Recommended Posts

I've found this multi-file copy script from the German AutoIT forums:

Multi-filecopy

It has examples on how to either copy a folder full of files or an array of multiple files, with a progress bar for current progress as well as for total progress. Has anyone tried to modify this so it could do both at the same time? That is to say, have an array consisting of folders and individual files (e.g. C:\Doc and Settings\user1, C:\Doc and Settings\user2, c:\windows\file.txt, etc.)

The script is a bit above my current skillset, but I can see that if it finds an array, it only works for individual files, and that otherwise it looks like it only works for a single folder. Can any of you scriptmeisters offer a solution that would allow it to work as above? The multi-progressbar does a good job when copying large folders or files, but I'd love to see it work for multiple ones together.

Link to comment
Share on other sites

No takers?

I translated into English some things, but I have not tried it.

;===Needed======================================================================
#include<String.au3>
#include<Misc.au3>
Global $strFiles = '', $strSize = 0
;===============================================================================


;===Example 1 (create the file "!copydata.mfc" in the source directory)=========
Global $sSourcePath = 'C:\Programme\AutoIt3\Examples\'

Global $aReturn = _MultiFileCopy($sSourcePath)

MsgBox(0, 'MFC', '"!copydata.mfc" has been created!')
;===============================================================================


;===Example 2 (complete list copy )=============================================
; Are all files and subdirectories (recursively) copy
; Directory structure of the source is assumed
Global $sSourcePath = 'C:\Programme\AutoIt3\Examples\'
Global $sDestinationPath = @ScriptDir & '\Tmp1'; Target path (may be created)

Global $aReturn = _MultiFileCopy($sSourcePath, $sDestinationPath, False)
;===============================================================================


;===Example 3 (copy multiple files )============================================
; All files from the array are copied into the target directory
; Array[0], the number of files to copy contained
Global $aSource[4] = [3, @SystemDir & '\shell32.dll', @SystemDir & '\mspaint.exe', @SystemDir & '\eula.txt']
Global $sDestinationPath = @ScriptDir & '\Tmp2'; Target path (may be created)

Global $aReturn = _MultiFileCopy($aSource, $sDestinationPath, False)
;===============================================================================



;===============================================================================
; Function Name:   _MultiFileCopy
; Description::    Copies multiple files with progressbar
; Parameter(s):    Array of files to copy or source path,
;                  Target path,
;                  overwrite? [True/False],
;                  If overwrite = True, prefix to overwrite
; Return Value(s): Array containing the copied files
; Requirement(s):  Global $strFiles = '', $strSize = 0
;                  #include<String.au3>
;                  #include<Misc.au3>
; Author(s):       Tom99, progandy, eukalyptus and Oscar (www.autoit.de)
;===============================================================================
Func _MultiFileCopy($aSource, $sDestPath = '', $bOverWrite = True, $sPreFix = '!Copy')
    Local $oldGUICloseOnESC = Opt('GUICloseOnESC', 0)
    Local $ret, $sShowSource, $sShowDest, $sSourcePath = '', $sNewFolder = '', $k
    Local $aMFC[12] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, False, DllOpen('user32.dll')]
    If IsArray($aSource) Then
        If Not IsNumber($aSource[0]) Then Return SetError(1, 0, 0)
        For $i = 1 To $aSource[0]
            $aMFC[7] += FileGetSize($aSource[$i])
        Next
    Else
        $sSourcePath = $aSource
        If StringRight($sSourcePath, 1) <> '\' Then $sSourcePath &= '\'
        $strSize = 0
        ToolTip('Please wait! Directory will be read!', @DesktopWidth / 2 - 100, 10)
        If FileExists($sSourcePath & '!copydata.mfc') And $sDestPath <> '' Then
            Local $sFile = StringTrimRight(FileRead($sSourcePath & '!copydata.mfc'), 2)
            $strSize = StringLeft($sFile, StringInStr($sFile, @CRLF) - 1)
            $aSource = StringSplit(StringTrimLeft($sFile, StringInStr($sFile, @CRLF) + 1), @CRLF, 1)
        Else
            If FileExists($sSourcePath & '!copydata.mfc') Then FileDelete($sSourcePath & '!copydata.mfc')
            $aSource = _GetFilesFolder_Rekursiv($sSourcePath)
            Local $hFile = FileOpen($sSourcePath & '!copydata.mfc', 2)
            If $hFile <> -1 Then
                FileWriteLine($hFile, $strSize)
                For $i = 1 To $aSource[0]
                    FileWriteLine($hFile, $aSource[$i])
                Next
                FileClose($hFile)
            EndIf
        EndIf
        $aMFC[7] = $strSize
        ToolTip('')
        If $sDestPath = '' Then Return SetError(0, 0, 1)
    EndIf
    If StringRight($sDestPath, 1) <> '\' Then $sDestPath &= '\'
    If Not FileExists($sDestPath) Then
        If Not DirCreate($sDestPath) Then Return SetError(2, 0, 0)
    EndIf
    $sShowDest = StringRegExpReplace($sDestPath, '(.{15})(.*)(.{35})', '$1' & '[...]' & '$3')
    Local $aReturn = $aSource
    Local $callback = DllCallbackRegister('__Progress', 'int', 'uint64;uint64;uint64;uint64;dword;dword;ptr;ptr;str')
    Local $ptr = DllCallbackGetPtr($callback)
    Local $DllKernel32 = DllOpen('kernel32.dll')
    __ProgressCreate($aMFC)
    $aMFC[9] = TimerInit()
    For $i = 1 To $aSource[0]
        $sArray = ''
        For $j = 0 To 11
            $sArray &= $aMFC[$j] & ';'
        Next
        $sFile = StringMid($aSource[$i], StringInStr($aSource[$i], '\', 0, -1) + 1)
        If $sSourcePath <> '' Then
            $sNewFolder = StringTrimLeft(StringLeft($aSource[$i], StringInStr($aSource[$i], '\', 0, -1)), StringLen($sSourcePath))
            If Not FileExists($sDestPath & $sNewFolder) Then
                If Not DirCreate($sDestPath & $sNewFolder) Then Return SetError(3, 0, 0)
            EndIf
        EndIf
        If $sFile = '' Then ContinueLoop
        $k = 0
        While $bOverWrite = False And FileExists($sDestPath & $sNewFolder & $sFile)
            $k += 1
            $sFile = $sPreFix & $k & "_" & StringMid($aSource[$i], StringInStr($aSource[$i], '\', 0, -1) + 1)
        WEnd
        $aReturn[$i] = $sDestPath & $sNewFolder & $sFile
        $sShowSource = StringRegExpReplace($aSource[$i], '(.{15})(.*)(.{35})', '$1' & '[...]' & '$3')
        GUICtrlSetData($aMFC[1], 'Kopiere Datei ' & @CRLF & '"' & $sShowSource & '"' & @CRLF & 'nach: "' & $sShowDest & '"')
        $ret = DllCall($DllKernel32, 'int', 'CopyFileExA', 'str', $aSource[$i], 'str', $aReturn[$i], 'ptr', $ptr, 'str', $sArray, 'int', 0, 'int', 0)
;~      ConsoleWrite('Return: ' & $ret[0] & @LF)
        If $ret[0] = 0 Then $aMFC[10] = True
        $aMFC[8] += FileGetSize($aSource[$i])
    Next
    DllClose($DllKernel32)
    DllCallbackFree($callback)
    GUIDelete($aMFC[0])
    DllClose($aMFC[11])
    Opt('GUICloseOnESC', $oldGUICloseOnESC)
    Return $aReturn
EndFunc   ;==>_MultiFileCopy

Func __Progress($FileSize, $BytesTransferred, $StreamSize, $StreamBytesTransferred, $dwStreamNumber, $dwCallbackReason, $hSourceFile, $hDestinationFile, $lpData)
    Local $aSplit = StringSplit(StringTrimRight($lpData, 1), ";")
    If $aSplit[11] = 'True' Then Return 1
    Local $pos = GUIGetCursorInfo($aSplit[1])
    If _IsPressed('1B', Int($aSplit[12])) Then Return 1
    If _IsPressed('01', Int($aSplit[12])) And ($pos[4] = Int($aSplit[7])) Then Return 1
    Local $sPercent = Round($BytesTransferred / $FileSize * 100, 0), $iTime, $iTotalTime, $iTransferRate
    Local $sPercentAll = Round(($aSplit[9] + $BytesTransferred) / $aSplit[8] * 100, 0)
    $iTime = TimerDiff($aSplit[10])
    $iTotalTime = Ceiling($iTime / 1000 / ($sPercentAll + 0.1) * 100)
    $iTransferRate = _StringAddThousandsSep(Int($aSplit[8] / $iTotalTime / 1000), '.', ',')
    GUICtrlSetData($aSplit[3], $sPercent & ' %')
    GUICtrlSetData($aSplit[5], $sPercent)
    GUICtrlSetData($aSplit[4], $sPercentAll & ' %    Time: ' & Int($iTime / 1000) & '/' & $iTotalTime & ' s    (' & $iTransferRate & ' KB/s)')
    GUICtrlSetData($aSplit[6], $sPercentAll)
EndFunc   ;==>__Progress

Func __ProgressCreate(ByRef $aMFC)
    If Not IsDeclared('WS_POPUPWINDOW') Then Local Const $WS_POPUPWINDOW = 0x80880000
    If Not IsDeclared('WS_EX_TOPMOST') Then Local Const $WS_EX_TOPMOST = 0x00000008
    If Not IsDeclared('WS_EX_TOOLWINDOW') Then Local Const $WS_EX_TOOLWINDOW = 0x00000080
    If Not IsDeclared('WS_EX_COMPOSITED') Then Local Const $WS_EX_COMPOSITED = 0x02000000
    $aMFC[0] = GUICreate('MultiFileCopy', 480, 220, -1, -1, $WS_POPUPWINDOW, BitOR($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW, $WS_EX_COMPOSITED))
    $aMFC[1] = GUICtrlCreateLabel('', 10, 10, 460, 65)
    GUICtrlSetFont(-1, 10, 400, 0, 'Courier New')
    GUICtrlCreateLabel('File:', 10, 83, 60, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[2] = GUICtrlCreateLabel('0 %', 80, 83, 390, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[4] = GUICtrlCreateProgress(10, 100, 460, 20)
    GUICtrlCreateLabel('Total:', 10, 133, 60, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[3] = GUICtrlCreateLabel('0 %', 80, 133, 390, 16)
    GUICtrlSetFont(-1, 11, 600, 0, 'Courier New')
    $aMFC[5] = GUICtrlCreateProgress(10, 150, 460, 20)
    $aMFC[6] = GUICtrlCreateButton('Cancel', 200, 185, 75, 25)
    GUICtrlSetFont(-1, 9, 400, 0, 'Arial')
    GUISetState()
EndFunc   ;==>__ProgressCreate

;==================================================================================================
; Function Name:   _GetFilesFolder_Rekursiv($sPath [, $sExt='*' [, $iDir=-1 [, $iRetType=0 ,[$sDelim='0']]]])
; Description:     Recursive list of files and / or folders
;                  Adaptation: directory size determined for _MultiFileCopy ($strSize)
; Parameter(s):    $sPath     the base path for the listing ('.' -current path, '..' -Parent path)
;                  $sExt      Extension to file selector '*' or -1 for all (default)
;                  $iDir      -1 Files folder (default), 0 only files, 1 folders only
;      optional:   $iRetType  0 returns Array, 1 returns String
;      optional:   $sDelim    specifies the separator for String Return
;                             0 -@CRLF (Default)  1 -@CR  2 -@LF  3 -';'  4 -'|'
; Return Value(s): Array (Default) od string with the found paths of files and / or folders
;                  Array[0] contains the number of files / folders
; Author(s):       BugFix (bugfix@autoit.de)
;==================================================================================================
Func _GetFilesFolder_Rekursiv($sPath, $sExt='*', $iDir=-1, $iRetType=0, $sDelim='0')
    Global $oFSO = ObjCreate('Scripting.FileSystemObject')
    Global $strFiles = ''
    Switch $sDelim
        Case '1'
            $sDelim = @CR
        Case '2'
            $sDelim = @LF
        Case '3'
            $sDelim = ';'
        Case '4'
            $sDelim = '|'
        Case Else
            $sDelim = @CRLF
    EndSwitch
    If ($iRetType < 0) Or ($iRetType > 1) Then $iRetType = 0
    If $sExt = -1 Then $sExt = '*'
    If ($iDir < -1) Or ($iDir > 1) Then $iDir = -1
    _ShowSubFolders($oFSO.GetFolder($sPath),$sExt,$iDir,$sDelim)
    If $iRetType = 0 Then
        Local $aOut
        $aOut = StringSplit(StringTrimRight($strFiles, StringLen($sDelim)), $sDelim, 1)
        If $aOut[1] = '' Then
            ReDim $aOut[1]
            $aOut[0] = 0
        EndIf
        Return $aOut
    Else
        Return StringTrimRight($strFiles, StringLen($sDelim))
    EndIf
EndFunc

Func _ShowSubFolders($Folder, $Ext='*', $Dir=-1, $Delim=@CRLF)
    If Not IsDeclared("strFiles") Then Global $strFiles = ''
    If ($Dir = -1) Or ($Dir = 0) Then
        For $file In $Folder.Files
            If $Ext <> '*' Then
                If StringRight($file.Name, StringLen($Ext)) = $Ext Then
                    $strSize += $file.size
                    $strFiles &= $file.Path & $Delim
                EndIf
            Else
                $strSize += $file.size
                $strFiles &= $file.Path & $Delim
            EndIf
        Next
    EndIf
    For $Subfolder In $Folder.SubFolders
        If ($Dir = -1) Or ($Dir = 1) Then $strFiles &= $Subfolder.Path & '\' & $Delim
        _ShowSubFolders($Subfolder, $Ext, $Dir, $Delim)
    Next
EndFunc
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...