Jump to content
Sign in to follow this  
jbennett

File copy to only copy files that are new or changed

Recommended Posts

jbennett

Hi everyone,

I'm just wondering, how can I copy files to a directory that are only new or changed?

Thanks

Regards,

Jon Bennett

Share this post


Link to post
Share on other sites
muncherw

You could use FileGetTime and compare timestamps and if they are different copy the files over.


Other People's Stuff:Andy Flesner's AutoIt v3: Your Quick Guide[topic="34302"]Locodarwin's ExcelCom_UDF[/topic][topic="61090"]MrCreatorR's Opera Library[/topic]

Share this post


Link to post
Share on other sites
jbennett

Thanks for the reply.

Got a quick question.

I have about 100 files ish. If I compared all the files then would this take quite a long time?.

I presume I would need to do something like "\*" and compare the local files with the files stored on the backup and if they are different then copy them.

Thought it was going to be easier than this but I guess I will just have to create some code to deal with this.

Thanks

Share this post


Link to post
Share on other sites
senthor

Hi Jon!

No, 100 files isn't very much,don't worry.

Just list the selected files to an array and check them in a "For"- loop.

That shouldN#t take too much time.

Best regards,

senthor

f.ex. (didn't check it:)

#include <file.au3>
#include <date.au3>
$aNormal = _FileListToArray("C:\My docs")
local $sText
For $iCount = 1 to $aNormal[0]
    If FileExists("C:\Backup\" & $aNormal[$iCount]) then 
        $aNormFile = FileGetTime("C:\My docs\" & $aNormal[$iCount])
        $aNormFile = $aNormFile[0] & "/" & $aNormFile[1] & "/" & $aNormFile[2] & " " & $aNormFile[3] & ":" &  $aNormFile[4] & ":" &  $aNormFile[5]
        $aBackFile = FileGetTime("C:\Backup\" & $aNormal[$iCount])
        $aBackFile = $aBackFile[0] & "/" & $aBackFile[1] & "/" & $aBackFile[2] & " " & $aBackFile[3] & ":" &  $aBackFile[4] & ":" &  $aBackFile[5]
        If _DateDiff("s", $aNormFile, $aBackFile) > 0 Then
            FileCopy("C:\My docs\" & $aNormal[$iCount], "C:\Backup\" & $aNormal[$iCount])
            $sText &= $aNormal[$iCount] & @crlf
        EndIf
    Else
        FileCopy("C:\My docs\" & $aNormal[$iCount], "C:\Backup\" & $aNormal[$iCount])
        $sText &= $aNormal[$iCount] & @crlf
    EndIf
Next
Msgbox(0,"Files copied:", $sText)
Edited by senthor

Share this post


Link to post
Share on other sites
jbennett

Thanks

The only problem is this code doesn't work with folders

Regards,

Jon

Share this post


Link to post
Share on other sites
PsaltyDS

Thanks for the reply.

Got a quick question.

I have about 100 files ish. If I compared all the files then would this take quite a long time?.

I presume I would need to do something like "\*" and compare the local files with the files stored on the backup and if they are different then copy them.

Thought it was going to be easier than this but I guess I will just have to create some code to deal with this.

Thanks

Sometimes the command line can do powerful things for you, like list all files in descending date/time order:
#include <Constants.au3>
#include <Array.au3>

$sExtCmd = @ComSpec & ' /c DIR "' & @DocumentsCommonDir & '" /A:-D /O:D /T:W'
$iPID = Run($sExtCmd, @DocumentsCommonDir, @SW_HIDE, $STDOUT_CHILD)
$sStdOut = ""
Do
    $sStdOut &= StdoutRead($iPID)
Until ProcessExists($iPID) = 0

$avStdOut = StringSplit($sStdOut, @CRLF, 1)
For $n = $avStdOut[0] To 1 Step -1
; Delete unwanted lines from array
    If (StringStripWS($avStdOut[$n], 8) = "") Or _
            (StringIsInt(StringLeft($avStdOut[$n], 2)) = 0) Or _
            (StringMid($avStdOut[$n], 3, 1) <> "/") Then _ArrayDelete($avStdOut, $n)
Next
$avStdOut[0] = UBound($avStdOut) - 1
_ArrayDisplay($avStdOut, "Files sorted by date/time");### Tidy Error -> for is never closed in your script.

You could get into the COM scripting interface to FileSystemObject and get quite geeky, but the basics still work fairly well.

:mellow:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
jbennett

Thanks.

I'm a bit confused what the code is checking though :-)

Cheers, Jon

Share this post


Link to post
Share on other sites
senthor

#include <file.au3>
#include <date.au3>
$aNormal = _FileListTreeToArray("C:\My docs", 1, "-D")
local $sText
For $iCount = 1 to $aNormal[0]
    If FileExists("C:\Backup\" & $aNormal[$iCount]) then 
        $aNormFile = FileGetTime("C:\My docs\" & $aNormal[$iCount])
        $aNormFile = $aNormFile[0] & "/" & $aNormFile[1] & "/" & $aNormFile[2] & " " & $aNormFile[3] & ":" &  $aNormFile[4] & ":" &  $aNormFile[5]
        $aBackFile = FileGetTime("C:\Backup\" & $aNormal[$iCount])
        $aBackFile = $aBackFile[0] & "/" & $aBackFile[1] & "/" & $aBackFile[2] & " " & $aBackFile[3] & ":" &  $aBackFile[4] & ":" &  $aBackFile[5]
        If _DateDiff("s", $aNormFile, $aBackFile) > 0 Then
            FileCopy("C:\My docs\" & $aNormal[$iCount], "C:\Backup\" & $aNormal[$iCount], 9)
            $sText &= $aNormal[$iCount] & @crlf
        EndIf
    Else
        FileCopy("C:\My docs\" & $aNormal[$iCount], "C:\Backup\" & $aNormal[$iCount], 9)
        $sText &= $aNormal[$iCount] & @crlf
    EndIf
Next
Msgbox(0,"Files copied:", $sText)

; Name...........: _FileListTreeToArray
; Description ...: List all files from the wished directiry with all files from all subfolders to an array.
; Syntax.........: _FileListTreeToArray($sPath[, $fRelation = 1[, $sType = ""[,$sSort = "N"]]])
; Parameters ....: $sPath - Path to the directory that has to be listed
;                  $fRelation - Optional: Path return type, "0" = absolute (default), "1" = relative
;                  $sType - Optional: Search type, see helptopic "FileGetAttrib"; possible : "RASHD", with "-" before for negotation:
;                  |R - Readonly
;                  |A - Archive
;                  |S - System
;                  |H - Hidden
;                  |D - Directory
;                  $sSort - Optional: Sort results, see "cmd.exe /K dir /?" at subpoint "order", with "-" before for negotation: possibilities:
;                  |N - Name, alphabetically
;                  |S - Size, smaller files first
;                  |E - Extension, alphabetically
;                  |D - Date/Time, older files first
;                  |G - Directories first
; Return values .: Success - Array with $array[0] = Number of items, $array[n] = path of items
;                  Failure - Returns 0 and Sets @Error:
;                  |0 - No error.
;                  |1 - Invalid $sPath
;                  |2 - Invalid $fRelation
;                  |3 - Invalid $sType
;                  |4 - Invalid $sSort
;                  |5 - User32.dll failure
; Author ........: Jonas Neef
; Remarks .......: Caution: This function can take very long! Wildcards are supported.
; Related .......: FileGetAttrib, FileSetAttrib, _FileListToArray
; Link ..........;
; Example .......; Yes
Func _FileListTreeToArray($sPath, $fRelation = 0, $sType = "", $sSort = "N")
    local $aCheck, $vStdout, $sTemp, $sPlaceholder, $sTempSort, $vStdout, $sLine, $iCounter, $aReturn
    ; Check parameters, validate path
    $aCheck = StringLeft($sPath, 3)
    $aCheck = StringSplit($aCheck, ":" )
    If $aCheck[0] <> 2 and StringLeft($sPath, 1) <> "\" then $sPath = @WorkingDir & "\" & $sPath
    If $aCheck[0] <> 2 and StringLeft($sPath, 1) = "\" then $sPath = @WorkingDir & $sPath
    If StringRight($sPath, 1) = "\" then $sPath = StringTrimRight($sPath, 1)
    If Not FileExists($sPath) then Return Seterror(1, 0, 0)
    if $fRelation > 1 OR $fRelation < 0 then return Seterror(2, 0, 0)
    $sTempSort = StringReplace($sSort, "-", "")
    If StringLen($sTempSort) <> 1 or _
        $sTempSort <> "N" and _
        $sTempSort <> "S" and _
        $sTempSort <> "E" and _
        $sTempSort <> "D" and _
        $sTempSort <> "G" and _
        $sTempSort <> "" then _
        return Seterror(3, 0, 0)
    If Stringreplace( _
        Stringreplace( _
        Stringreplace( _
        Stringreplace( _
        Stringreplace( _
        Stringreplace($sType, "-", "") _
        , "H", "") _
        , "S", ""), _
        "A", ""), _
        "R", ""), _
        "D", "") <> "" then _
        return Seterror(4,0,0)
    ; Start CMD to load the tree
    If $sType = "" Then
        $vStdout = Run(@comspec & ' /C cd ..\..\..\..\.. & dir "' & $sPath & '" /A /B /O:' & $sSort & ' /S', @workingdir, @SW_HIDE, 6)
    Else
        $vStdout = Run(@comspec & ' /C cd ..\..\..\..\.. & dir "' & $sPath & '" /A:' & $sType & ' /B /O:' & $sSort & ' /S', @workingdir, @SW_HIDE, 6)
    EndIF
    ; Get data via Stdout
    While 1
        $sLine = StdoutRead($vStdout)
        If @error Then ExitLoop
        If $sLine <> "" then $sTemp &= $sLine
    Wend
    ; Create Placeholder for hole string
    For $iCounter = 0 To StringLen($sTemp)
        $sPlaceholder &= "  "
    Next
    ; Convert string from extended Ascii to Ansi
    $sTemp = DllCall("user32.dll", "long", "OemToChar", "str", $sTemp, "str", $sPlaceholder)
    $sPlaceholder = ""
    If Not Isarray($sTemp) or $sTemp[0] < 1 then return Seterror(5,0,0)
    $sTemp = $sTemp[2]
    ; Format finally
    $sTemp = StringReplace($sTemp, @crlf, @lf)
    $sTemp = StringReplace($sTemp, @cr, @lf)
    If StringRight($sTemp, 1) = @lf then $sTemp = StringTrimRight($sTemp, 1)
    If StringLeft($sTemp, 1) = @lf then $sTemp = StringTrimLeft($sTemp, 1)
    If Not StringInStr($sTemp, @lf) then
        If $sTemp = "" then
            local $aReturn[1] = [0]
        Else
            local $aReturn[2] = [1, $sTemp]
        EndIf
    Else
        local $aReturn = StringSplit($sTemp, @lf)
    EndIF
    if not isarray($aReturn) then
        Return Seterror(5,0,0)
    EndIF
    ; If relative path is chosen edit the paths
    If $fRelation = 1 Then
        For $iCounter = 1 To $aReturn[0] Step 1
            $aReturn[$iCounter] = StringReplace($aReturn[$iCounter], $sPath & "\", "")
        Next
    EndIf
    ; Return array
    return Seterror(0,0,$aReturn)
EndFunc   ;==>_FileReadTreeInArray

Edited by senthor

Share this post


Link to post
Share on other sites
PsaltyDS

Thanks.

I'm a bit confused what the code is checking though :-)

Cheers, Jon

It just gets a list of the files in an array in Date/Time order so it will be easy to find the ones you want. I was just pointing out that simple DOS command line stuff like DIR can help with this kind of thing. It's surprisingly fast too. Open a command line and do "DIR /?" to see what the switched did.

To use that for what you originally asked, you would have to define "new" better. I assumed "newer than a certain number of days", or something like that. If all you meant was "Archive bit set", then there are other things that might be even easier.

:mellow:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
dillonlim

Hi everyone,

I'm just wondering, how can I copy files to a directory that are only new or changed?

Thanks

Regards,

Jon Bennett

I know it's cool and all to write your own programs but have you considered using robocopy?

Share this post


Link to post
Share on other sites
jbennett

Hi,

I have used Robocopy before but for my situation I cannot use this.

Hopefully I can put together some simple code that will just overwrite modified files and copy new files. My biggest problem is that I want to keep the following function in place:

_FileCopy ($working_location, $backup_location & @computername)

Func _FileCopy($fromFile,$tofile)
    Local $FOF_RESPOND_YES = 16
    Local $FOF_SIMPLEPROGRESS = 256
    $winShell = ObjCreate("shell.application")
    $winShell.namespace($tofile).CopyHere($fromFile,$FOF_RESPOND_YES)
EndFunc

Thanks

Edited by jbennett

Share this post


Link to post
Share on other sites
jbennett

I can't. This code is part of a larger program that I've written.

At the moment i've got it to overwrite the data each time it runs the backup.

Just looking at ways of cutting down the amount of time it takes after the first backup.

cheers

p.s. thanks for the link to synctoy though, i've never heard of it before and I work as an IT Administrator so it could be quite useful in the future :-)

Edited by jbennett

Share this post


Link to post
Share on other sites
Bowmore

XCOPY is very quick and versatile for this sort of thing.

; Copy new and changed files including sub directories to Backup location
RunWait(@ComSpec & " /c " & "xcopy " & '"C:\Applications\AutoIt Scripts" "H:\Backup\Applications\AutoIt Scripts" /D /E /C /R /H /I /K /Y')

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Share this post


Link to post
Share on other sites
jbennett

That's a good idea :-)

RunWait(@ComSpec & " /c " & "xcopy " & '"C:\Applications\AutoIt Scripts" "H:\Backup\Applications\AutoIt Scripts" /D /E /C /R /H /I /K /Y')

How would I modify this so that I can use the data in my .ini file instead. Struggling to get it right.

I want to add 3 bits of information to this.

$working_location

$backup_location & @computername

Thanks

Edited by jbennett

Share this post


Link to post
Share on other sites
Danny35d

; Copy new and changed files including sub directories to Backup location
RunWait(@ComSpec & " /c " & 'xcopy "' & $working_location & '" "' & $backup_location & @computername & '" /D /E /C /R /H /I /K /Y')


AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line

Share this post


Link to post
Share on other sites
jbennett

Cheers for that.

I got it sorted yesterday evening in the end :-)

Have a good day :mellow:

Share this post


Link to post
Share on other sites
GaryC

Hi,

When I run xcopy with runwait() its output doesn't appear. When I added the option that causes handles to be inherited (not documented in the RunWait page) it would then show xcopy output when I ran the script from cmd prompt after compiling as a console program. However, when I redirected output with > or ran it from TextPad, my AutoIt script output appeared but the xcopy output did not. I think output from other commands, like dir, does appear. What's going on with xcopy?

Gary

Share this post


Link to post
Share on other sites
Gogi02

After i tried xcopy in a script i only got 100 or so dos windows opened and then closed without copiing anything. Can somebody help me out?

Share this post


Link to post
Share on other sites
mdwerne

After i tried xcopy in a script i only got 100 or so dos windows opened and then closed without copiing anything. Can somebody help me out?

Your best bet for help is to open a new topic and include your source code. It's hard to troubleshoot the issue based on the information you've given us.

-Mike

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  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.