Jump to content

Directory Copier... thing


taker4mdb
 Share

Recommended Posts

Just something I was playing around with... it copies whole directories only (including all subfolders and files).

The idea is that if an error is encountered when copying a large number of files, it won't stop copying (like Windows).

It has two options - overwrite files and batch mode (batch mode was my first attempt at this, it uses a hidden batch file to copy the files, monitoring the batches output to count the number of files processed. It's not neat or pretty, but it seems to go a little faster, so I crammed it in there!)

To use the batch mode, you need a batch file in the same directory as the script file (this gets deleted after it's used - made to be compiled with the .exe, extracted, executed, and deleted)

Contents of batch file (named MBCOPYFILES.bat):

@echo off

xcopy %1 %2 /e /c /h /r /y

And the script file:

#include <GUIConstants.au3>
#include <Array.au3>

GUICreate("Mike's File Copier", 300, 136)

GUICtrlCreateLabel("Copy files from directory:", 10, 10, 280, 13)
$txtFromDir = GUICtrlCreateInput("", 10, 23, 215, 20, $ES_READONLY)
$btnFromDir = GUICtrlCreateButton("Browse", 230, 23, 60, 20)

GUICtrlCreateLabel("To directory:", 10, 53, 280, 13)
$txtToDir = GUICtrlCreateInput("", 10, 66, 215, 20, $ES_READONLY)
$btnToDir = GUICtrlCreateButton("Browse", 230, 66, 60, 20)

$cbxOWMode = GUICtrlCreateCheckbox("Overwrite", 10, 96, 100, 13)
$cbxBatMode = GUICtrlCreateCheckbox("Batch Mode", 10, 114, 100, 13)

$btnCopy = GUICtrlCreateButton("Copy", 120, 102, 60, 20)

GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $cbxBatMode
            If GUICtrlRead($cbxBatMode) = $GUI_CHECKED Then
                GUICtrlSetState($cbxOWMode, $GUI_CHECKED)
                GUICtrlSetState($cbxOWMode, $GUI_DISABLE)
            Else
                GUICtrlSetState($cbxOWMode, $GUI_ENABLE)
            EndIf
        Case $btnFromDir
            GUICtrlSetData($txtFromDir, FileSelectFolder("Select source folder", "", 3))
        Case $btnToDir
            GUICtrlSetData($txtToDir, FileSelectFolder("Select destination folder", "", 3))
        Case $btnCopy
            If (GUICtrlRead($txtFromDir) = "") Or (GUICtrlRead($txtToDir) = "") Then
            ;Do nothing
            Else
                If GUICtrlRead($cbxBatMode) = $GUI_CHECKED Then
                ;Bat mode
                    $Timer = TimerInit()
                    mbBatchCopy(GUICtrlRead($txtFromDir), GUICtrlRead($txtToDir))
                    MsgBox(0, "Complete", "Copy completed in: " & Round(TimerDiff($Timer) / 1000, 0) & " seconds.")
                Else
                ;Normal mode
                    $Timer = TimerInit()
                    mbFileCopy(GUICtrlRead($txtFromDir), GUICtrlRead($txtToDir), mbGetOWMode())
                    MsgBox(0, "Complete", "Copy completed in: " & Round(TimerDiff($Timer) / 1000, 0) & " seconds.")
                EndIf
            EndIf
        Case $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd


Func mbFileCopy($from, $to, $ow)
    Dim $SD[1]
    Dim $DD[1]
    $SD[0] = $from
    $DD[0] = $to

    If StringRight($SD[0], 1) <> "\" Then
        $SD[0] = $SD[0] & "\"
    EndIf
    If StringRight($DD[0], 1) <> "\" Then
        $DD[0] = $DD[0] & "\"
    EndIf

    $SDS = DirGetSize($SD[0], 1)
    $FS = 0
    $FC = 0
    Dim $EC[1]
    $EC[0] = 0

    ProgressOn("Copying Files", "Initializing...", "0% Complete", -1, -1, 16)

    Do
        $Search = FileFindFirstFile($SD[0] & "*")
        If $Search = -1 Then
        ;Empty folder, continue with the next
        Else
            While 1
                $CF = FileFindNextFile($Search)
                If @error Then ExitLoop
                If StringInStr(FileGetAttrib($SD[0] & $CF), "D") = 0 Then;Is file a directory?
                ;Copy file
                    ProgressSet(Round(($FS / $SDS[0]) * 100, 0), Round(($FS / $SDS[0]) * 100, 0) & "% Complete" & @LF & "(" & $FC & " Files, " & Round($FS / 1048576, 2) & "MB)", "Copying file: " & StringTrimRight($CF, StringLen($CF) - 16) & "...")
                    If FileCopy($SD[0] & $CF, $DD[0] & $CF, $ow) = 0 Then
                        $EC[0] = $EC[0] + 1
                        _ArrayAdd($EC, $SD[0] & $CF)
                    EndIf
                    $FC = $FC + 1
                    $FS = $FS + FileGetSize($SD[0] & $CF)
                Else
                ;Create destination directory if it doesn't exist and queue directory
                    ProgressSet(Round(($FS / $SDS[0]) * 100, 0), Round(($FS / $SDS[0]) * 100, 0) & "% Complete" & @LF & "(" & $FC & " Files, " & Round($FS / 1048576, 2) & "MB)", "Creating directory: " & StringTrimRight($CF, StringLen($CF) - 16) & "...")
                    If FileExists($DD[0] & $CF) = 0 Then DirCreate($DD[0] & $CF)
                    ProgressSet(Round(($FS / $SDS[0]) * 100, 0), Round(($FS / $SDS[0]) * 100, 0) & "% Complete" & @LF & "(" & $FC & " Files, " & Round($FS / 1048576, 2) & "MB)", "Creating directory: " & StringTrimRight($CF, StringLen($CF) - 16) & "...")
                    _ArrayAdd($SD, $SD[0] & $CF & "\");"CurrentDir\FoundDir\"
                    _ArrayAdd($DD, $DD[0] & $CF & "\");"DestDir\FoundDir\"
                EndIf
            WEnd
        EndIf
        
        If StringInStr(_ArrayToString($SD, "?"), "?") = 0 Then ExitLoop
        
        ProgressSet(Round(($FS / $SDS[0]) * 100, 0), Round(($FS / $SDS[0]) * 100, 0) & "% Complete" & @LF & "(" & $FC & " Files, " & Round($FS / 1048576, 2) & "MB)", "Removing directory from queue")
        FileClose($Search);Release search handle
        _ArrayDelete($SD, 0);---\
        _ArrayDelete($DD, 0);----Remove exhausted directories from the queue
    Until 0
    ProgressOff()
    
;Check for errors and write/open error log, if necessary
    If $EC[0] > 0 Then
        $EL = FileOpen("Error Log.txt", 2)
        FileWriteLine($EL, "Mike's File Copier - Error Log")
        FileWriteLine($EL, @MON & "/" & @MDAY & "/" & @YEAR & " - " & @HOUR & ":" & @MIN)
        FileWriteLine($EL, "")
        FileWriteLine($EL, "There following " & $EC[0] & " files were not copied:")
        $i = 0
        For $i = 1 to $EC[0]
            FileWriteLine($EL, $EC[$i])
        Next
        FileWriteLine($EL, "")
        FileWriteLine($EL, "-- End of error log --")
        FileWriteLine($EL, "")
        FileWriteLine($EL, "")
        FileClose($EL)
        
        Run("Notepad.exe Error Log.txt")
    EndIf
EndFunc  ;==>mbFileCopy

Func mbBatchCopy($strFrom, $strTo)
    $numSourceFiles = DirGetSize($strFrom, 1)
    $numCopiedFiles = 0
    
    If StringRegExp($strFrom, ".*\\$", 0) = 0 Then
        $strFrom = $strFrom & "\*.*"
    Else
        $strFrom = $strFrom & "*.*"
    EndIf
    If StringRegExp($strTo, ".*\\$", 0) = 0 Then
        $strTo = $strTo & "\"
    EndIf
    
    FileInstall("MBCOPYFILES.bat", "MBCOPYFILES.bat", 1)
    FileSetAttrib("MBCOPYFILES.bat", "+H")
    $CopyBatch = Run('MBCOPYFILES.bat "' & $strFrom & '" "' & $strTo & '"', "", @SW_HIDE, 2)
    
    ProgressOn("Copying Files", "Initializing...", "0% Complete")
    While ProcessExists($CopyBatch)
        $STDOUT = StringRegExp(StdoutRead($CopyBatch), ":.*.{3}\b", 3)
        _ArrayAdd($STDOUT, "ENDOFARRAY")
        $numCopiedFiles = $numCopiedFiles + mbArrayGetSize($STDOUT)
        ProgressSet(Round(($numCopiedFiles / $numSourceFiles[1]) * 100, 0), Round(($numCopiedFiles / $numSourceFiles[1]) * 100, 0) & "% Complete", $numCopiedFiles & " files copied")
        Sleep(100)
    WEnd
    ProgressOff()
    
    FileDelete("MBCOPYFILES.bat")
EndFunc  ;==>mbBatchCopy


Func mbArrayGetSize($array)
    If IsArray($array) = 0 Then
        Return -1
    EndIf
    $index = 0
    $count = 0
    While 1
        If $array[$index] = "ENDOFARRAY" Then
            ExitLoop
        Else
            $count = $count + 1
            $index = $index + 1
        EndIf
    WEnd
    
    Return $count
EndFunc  ;==>mbArrayGetSize

Func mbGetOWMode()
    If GUICtrlRead($cbxOWMode) = $GUI_CHECKED Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc  ;==>mbGetRecMode
Link to comment
Share on other sites

looks great. I actually need to look through that. I have been trying to figure out how to do some of that for a little while, depending on how you did it. If you could give me a brief explanation on how you got it to copy over directories within directories without using DirCopy(), thatd be great, if not, I will look harder.

EDIT: figured it out. You just added a new directory to the array (queue) and deleted the first in line (already used), continually searching the first for new files. A little wordy, and poor variable names..., but otherwise very nicely done.

Edited by crzftx
Link to comment
Share on other sites

  • 2 weeks later...

Hi there,

It's pretty cool code and so nice of you to share your codes. I wanna check with you if there anyway to get the file size and modified date of the filter file. I attached my code below and your great suggestion is truly appreciated. In fact, the script is just to monitor the filter file name, size and modified date and to be reported in a text file.

#Include <File.au3>

#Include <Array.au3>

$a = "C:\"

$b = "C:\Temp\Report.txt"

$FileList=_FileListToArray($a,"*.exe",1)

If @Error=1 Then

MsgBox (0,"","No Files\Folders Found.")

Exit

EndIf

_ArrayDelete($Filelist,0)

_FileWriteFromArray($b,$FileList,1)

I just start to learn the autoit and try to understand better. Perhaps my code is not enhanced like yours.

Link to comment
Share on other sites

Uh, look for the helpfile, it's called support-switch.htm in the source-dir.

Basicly, it's a gui for robocopy (that's Robust File Copy Utility, a nice piece of free software from microsoft) that may help you to create backup-scripts or run it in background.

As you can see, there are a lot of options, since it's a kind of server tool for admins. In my company, we use robocopy to backup parts of our file-server. To get you started, the robocopy-gui may be a help.

So read the fine manual.

Edited by dabus
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...