Jump to content

Simple Robocopy with Progressbar


Marc
 Share

Recommended Posts

Hi all,

just a little script I find useful. Always wanted to have an easy way to copy/mirror a complete folder with some kind of progressbar.

Since robocopy is reliable and pre-installed in windows 10, it's the easiest way to achieve a copy of a folder. But there is no gui, the plain dosbox looks ugly... so I came up with this.

It's a simple script, some would call it a stupid wrapper. The only interesting part of it is the ability to display progressbars for copied bytes and copied files.

The script launches robocopy two times: at the first run, robocopy gets called with the /L Parameter, so it just logs what it WOULD do. So the script gathers the number of files and bytes which have to be processed. After that, robocopy gets called to actually do the job and the logfile is read out and compared to the total amount of files/bytes.

Warning: there are two possible modes supported: copy and mirror. For gods and your own sake, if you don't know what "mirror" does, do not use this! Short Explanation: "mirror" will force the destination folder to be an exact copy of the source folder, so if there are files in the destination folder which are not in the source folder, robocopy will kill them without any warning!

have fun,
Marc

 

robocopy.au3

Edited by Marc
typo

Any of my own codes posted on the forum are free for use by others without any restriction of any kind. (WTFPL)

Link to comment
Share on other sites

  • 3 weeks later...

Thank you for sharing! By the way, Marc, if something interrupts the copy half-way (a PC crash or something), will the copy when restarted pickup where it left off, or will it start all over (maybe ignoring files that were completely copied)?

Thanks!

Link to comment
Share on other sites

The copy will restart (not resume), but it will only copy changed or non-copied files, skipping already copied, non-changed files.

Edited by spudw2k
Link to comment
Share on other sites

On 6/26/2019 at 8:06 AM, JLogan3o13 said:

Aside from the German ConsoleWrites, very nice :)

auf Englistch ... but really the locale can be used to make a translation for any language ... I add the parameter "$s_Lng" - and anyone can make new language for the GUI.

Default German because, of course .. it is. 😁

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <ProgressConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

$s_Lng = RegRead("HKEY_USERS\.DEFAULT\Control Panel\International", "LocaleName") ; to determine locale

robocopy("c:\tools", "d:\tools", "c:\tools\logfile.txt", "copy") ; example only

Func readlog($logfilepath, ByRef $bytes, ByRef $lines)
    $bytes = 0
    $logfile = FileOpen($logfilepath, 0)
    $lines = -1  ; number of files = number of lines in logfile -1
    While 1
        $line = FileReadLine($logfile)
        If @error Then ExitLoop
        $lines += 1
        $position = StringInStr($line, @TAB, 0, -1)
        If $position > 0 Then
            $tmpbytes = StringLeft($line, $position - 1)
            $tmpbytes = StringStripWS($tmpbytes, 3)
            $tmpbytes = Int($tmpbytes)
            $bytes += $tmpbytes
        EndIf
    WEnd
    FileClose($logfile)
EndFunc   ;==>readlog

Func robocopy($source, $destination, $logfilepath, $params)
    ConsoleWrite($source & ", " & $destination & ", " & $logfilepath & ", " & $params & @CRLF)
    Local $totalbytes = 0
    Local $totalfiles = 0
    Local $donebytes = 0
    Local $donefiles = 0

    ; check if pathes end with a \ then remove it
    If StringRight($source, 1) = "\" Then $source = StringLeft($source, StringLen($source) - 1)
    If StringRight($destination, 1) = "\" Then $destination = StringLeft($destination, StringLen($destination) - 1)

    Switch $params
        Case "mirror"
            $params = "/mir /mt /np /ndl /nc /bytes /njh /njs /e"
        Case "copy"
            $params = "/mt /np /ndl /nc /bytes /njh /njs /e"
    EndSwitch

    RunWait(@ComSpec & ' /c ' & 'robocopy.exe "' & $source & '" "' & $destination & '" ' & $params & ' /log:"' & $logfilepath & '" /l', @TempDir, @SW_HIDE)
    readlog($logfilepath, $totalbytes, $totalfiles)
    If $totalbytes = 0 Then Exit

    $str_total_bytes = StringRegExpReplace($totalbytes, '(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))', '\1.')
    $str_total_files = StringRegExpReplace($totalfiles, '(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))', '\1.')
    Select
        Case StringInStr($s_Lng, "en")
            ConsoleWrite("Total Bytes: " & $str_total_bytes & @CRLF)
            ConsoleWrite("Total Files: " & $str_total_files & @CRLF)
        Case Else
            ConsoleWrite("Gesamte Bytes: " & $str_total_bytes & @CRLF)
            ConsoleWrite("Gesamte Files: " & $str_total_files & @CRLF)
    EndSelect


    $Form1 = GUICreate("RoboCopy GUI", 580, 180, 192, 124)
    Select
        Case StringInStr($s_Lng, "en")
            GUICtrlCreateLabel("Source", 16, 12, 36, 17)
        Case Else
            GUICtrlCreateLabel("Quelle", 16, 12, 36, 17)
    EndSelect
    $quelle = GUICtrlCreateInput("", 60, 8, 500, 21)
    GUICtrlSetState($quelle, $GUI_DISABLE)
    Select
        Case StringInStr($s_Lng, "en")
            GUICtrlCreateLabel("Target", 16, 44, 36, 17)
        Case Else
            GUICtrlCreateLabel("Ziel", 16, 44, 36, 17)
    EndSelect
    $ziel = GUICtrlCreateInput("", 60, 40, 500, 21)
    GUICtrlSetState($ziel, $GUI_DISABLE)
    $lbl_files = GUICtrlCreateLabel("", 16, 72, 560, 17)
    $Progress1 = GUICtrlCreateProgress(16, 88, 544, 25)
    $lbl_bytes = GUICtrlCreateLabel("", 16, 120, 560, 17)
    $Progress2 = GUICtrlCreateProgress(16, 136, 544, 25)
    GUISetState(@SW_SHOW)

    GUICtrlSetData($quelle, $source)
    GUICtrlSetData($ziel, $destination)

    FileDelete($logfilepath)
    $pid = Run(@ComSpec & ' /c ' & 'robocopy.exe "' & $source & '" "' & $destination & '" ' & $params & ' /log:"' & $logfilepath & '"', @TempDir, @SW_HIDE)
    While ProcessExists($pid)
        Sleep(500)
        readlog($logfilepath, $donebytes, $donefiles)
        $str_done_bytes = StringRegExpReplace($donebytes, '(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))', '\1.')
        $str_done_files = StringRegExpReplace($donefiles, '(\A\d{1,3}(?=(\d{3})+\z)|\d{3}(?=\d))', '\1.')
        $percent_bytes = $donebytes * 100 / $totalbytes
        $percent_files = $donefiles * 100 / $totalfiles
        Select
            Case StringInStr($s_Lng, "en")
                ConsoleWrite("Bytes Copied: " & $str_done_bytes & ", percent complete: " & $percent_bytes & "%" & @CRLF)
                ConsoleWrite("Files Copied: " & $str_done_files & ", percent complete: " & $percent_files & "%" & @CRLF)
                GUICtrlSetData($Progress1, $percent_bytes)
                GUICtrlSetData($Progress2, $percent_files)
                GUICtrlSetData($lbl_bytes, $str_done_bytes & " of " & $str_total_bytes & " (" & StringFormat("%.2f", $percent_bytes) & "%)")
                GUICtrlSetData($lbl_files, $str_done_files & " of " & $str_total_files & " (" & StringFormat("%.2f", $percent_files) & "%)")
            Case Else
                ConsoleWrite("Erledigte Bytes: " & $str_done_bytes & ", entspricht : " & $percent_bytes & "%" & @CRLF)
                ConsoleWrite("Erledigte Files: " & $str_done_files & ", entspricht : " & $percent_files & "%" & @CRLF)
                GUICtrlSetData($Progress1, $percent_bytes)
                GUICtrlSetData($Progress2, $percent_files)
                GUICtrlSetData($lbl_bytes, $str_done_bytes & " von " & $str_total_bytes & " (" & StringFormat("%.2f", $percent_bytes) & "%)")
                GUICtrlSetData($lbl_files, $str_done_files & " von " & $str_total_files & " (" & StringFormat("%.2f", $percent_files) & "%)")
        EndSelect
    WEnd
        EndFunc   ;==>robocopy

        robocopy("c:\test", "d:\x", @TempDir & "\robocopy.log", "copy")

 

Always carry a towel.

Link to comment
Share on other sites

On 7/19/2019 at 9:43 PM, ModemJunki said:

auf Englistch ... but really the locale can be used to make a translation for any language ... I add the parameter "$s_Lng" - and anyone can make new language for the GUI.

Default German because, of course .. it is. 😁

Nice idea, like it. Makes the script more useable. 😁

Any of my own codes posted on the forum are free for use by others without any restriction of any kind. (WTFPL)

Link to comment
Share on other sites

  • 4 years later...

Not really sure what you want to achieve.

If you want the copied bytes displayed in MB/GB then take a look ath the lines

GUICtrlSetData($lbl_bytes, $str_done_bytes & " of " & $str_total_bytes & " (" & StringFormat("%.2f", $percent_bytes) & "%)")

you could use the function from guinnes here instead to format the value.

best regards,
Marc

Any of my own codes posted on the forum are free for use by others without any restriction of any kind. (WTFPL)

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

×
×
  • Create New...