amloessb

liveBackup.vbs (v1.2)

Apr 3rd, 2012
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'Live File Backup Script v1.2
  2. 'Written by Aaron Loessberg-Zahl
  3. 'Last modified 03 April 2012
  4. '
  5. 'Copies files from a source directory (or a single source file)
  6. 'to a backup destination as they are changed in the source.
  7. '
  8. 'This script must be run from the command line.
  9. '
  10. '_ _ _ ____ ____ _  _ _ _  _ ____   /
  11. '| | | |__| |__/ |\ | | |\ | | __  /
  12. '|_|_| |  | |  \ | \| | | \| |__] .  
  13. '
  14. '!!THIS SCRIPT DOES NOT RECURSE DOWN FOLDER TREES PROPERLY!!
  15. '
  16. 'I did not realize until after writing this script that VBScript does not do
  17. 'recursion properly.  For example, when calling folderCompareAndCopy
  18. 'recursively, strDestFolder will be overwritten by the subsequent calls, causing
  19. 'files to be placed in weird locations in the backup destination.  This only
  20. 'occurs with a directory tree of depth > 2.  For example, running
  21. 'cscript liveBackup.vbs "C:\Source" <some_destination> on the following tree is
  22. 'okay:
  23. '
  24. ' C:
  25. '  |_Source
  26. '     |_Folder A
  27. '     |  |_File 1
  28. '     |  |_File 2
  29. '     |_Folder B
  30. '        |_File 3
  31. '        |_File 4
  32. '
  33. 'Anything deeper will produce errors in the destination.
  34. '
  35. 'For comments/questions/bugs, please contact
  36. '
  37. ' ----------------------------------------------------------------------------
  38. ' "THE BEER-WARE LICENSE" (Revision 2659):
  39. ' <[email protected]> wrote this file. As long as you retain this
  40. ' notice, you can do whatever you want with this stuff. If we meet some day,
  41. ' and you think this stuff is worth it, you can buy me a beer in return.
  42. ' ----------------------------------------------------------------------------
  43. '
  44. 'Changelog:
  45. 'v1.2    04-03-2012  amloessb  Broken script is broken
  46. 'v1.1.1  11-11-2011  amloessb  Further fixed interval checking
  47. 'v1.1    11-11-2011  amloessb  Added check for non-numeric interval
  48. 'v1.0    11-09-2011  amloessb  First working version
  49.  
  50. Option Explicit
  51.  
  52. Dim objFSO, objSource, objDest, objChildren, objFiles, objDestFile, args
  53. Dim strSource, strDest, strDestFile, strFilename, strChoice, strAnswer, strHeader
  54. Dim subfolder, file, strDestFolder, objDestFolder, strNewFileList, strSize, strName
  55. Dim dateSrcModified, dateDestModified, dateModified
  56. Dim badAnswer, newFiles, isFileOp
  57. Dim objSubFol, objSubFiles, oSrc, oDest
  58. Dim oDestCDM, oSrcCDM, strSrcCDM, strDestCDM
  59. Dim oDestFCDM, oSrcFCDM, strSrcFCDM, strDestFCDM, strDestFolderFCDM, fileFCDM, subfolderFCDM
  60. Dim oSrcCC, oDestCC, destCC
  61. Dim oSrcFCC, oDestFCC, destFCC, fileFCC, subfolderFCC
  62. Dim intInterval
  63. Dim DTab, TTab
  64.  
  65. 'ynAnswer ()
  66. 'Purpose: Reads in an answer from StdIn, and loops if it is not "y" or "n"
  67. '         The case of the user's answer does not matter.
  68. 'Returns: the answer "y" or "n"
  69. Function ynAnswer ()
  70.     badAnswer = True
  71.     While badAnswer
  72.         WScript.StdIn.Read(0)
  73.         strChoice = WScript.StdIn.ReadLine()
  74.         If Lcase(strChoice) = "n" Then
  75.             ynAnswer = "n"
  76.             badAnswer = False
  77.         ElseIf Lcase(strChoice) = "y" Then
  78.             ynAnswer = "y"
  79.             badAnswer = False
  80.         Else
  81.             WScript.StdOut.Write "Please answer y or n > "
  82.         End If
  83.     WEnd
  84. End Function
  85.  
  86. 'confirmOp (src, dest, fileOp)
  87. 'Purpose: Asks the user to confirm the backup settings
  88. 'Returns: N/A
  89. 'Depends on ynAnswer
  90. Function confirmOp (src, dest, fileOp)
  91.     WScript.StdOut.Write "The script will now backup "
  92.     If Not fileOp Then
  93.         WScript.StdOut.Write "the contents of" & VBCrLf
  94.     Else
  95.         WScript.StdOut.Write VBCrLf
  96.     End If
  97.     WScript.Echo src
  98.     WScript.Echo "to"
  99.     WScript.Echo dest
  100.     WScript.Echo ""
  101.     WScript.StdOut.Write "Is this correct? [y/n] > "
  102.     strAnswer = ynAnswer()
  103.     If strAnswer = "n" Then
  104.         WScript.Quit 0
  105.     End If
  106. End Function
  107.  
  108. 'printCopyInfo (src)
  109. 'Purpose: Prints the time, name, and size of the given file or folder
  110. 'Returns: N/A
  111. Function printCopyInfo (src)
  112.     dateModified = src.DateLastModified
  113.     strSize = FormatNumber((src.Size / 1024.0), 2)
  114.     strName = src.Name
  115.     'WScript.StdOut.Write VBCrLf
  116.    WScript.Echo dateModified & VBTab & strName & VBTab & strSize & "K"
  117. End Function
  118.  
  119. 'compareDateModified (strSrc, strDest, strMsg)
  120. 'Purpose: Appends the file information to strMsg if the dest file is newer
  121. 'Returns: strMsg, with the file's entry appended if the dest file is newer
  122. Function compareDateModified (strSrcCDM, strDestCDM, strMsg)
  123.     If objFSO.FileExists(strDestCDM) Then
  124.         Set oDestCDM = objFSO.GetFile(strDestCDM)
  125.         Set oSrcCDM = objFSO.GetFile(objFSO.BuildPath(strSrcCDM,oDestCDM.Name))
  126.         dateSrcModified = oSrcCDM.DateLastModified
  127.         dateDestModified = oDestCDM.DateLastModified
  128.         If dateDestModified > dateSrcModified Then
  129.             compareDateModified = strMsg & oSrcCDM.Name & DTab & dateSrcModified & _
  130.                                   DTab & dateDestModified & VBCrLf
  131.         End If
  132.     End If
  133. End Function
  134.  
  135. 'folderCompareDateModified (strSrc, strDest, strMsg)
  136. 'Purpose: Recursive compareDateModified, by folder
  137. 'Returns: strMsg, appended to as necessary
  138. 'Depends on compareDateModified
  139. Function folderCompareDateModified (strSrcFCDM, strDestFCDM, strMsg)
  140.     If objFSO.FolderExists(strDestFCDM) Then
  141.         Set oSrcFCDM = objFSO.GetFolder(strSrcFCDM)
  142.         Set oDestFCDM = objFSO.GetFolder(strDestFCDM)
  143.         For Each fileFCDM In oSrcFCDM.Files
  144.             strMsg = compareDateModified(strSrcFCDM, objFSO.BuildPath(strDestFCDM, fileFCDM.Name), strMsg)
  145.         Next
  146.         For Each subfolderFCDM In objFSO.GetFolder(strSrcFCDM).SubFolders
  147.             strDestFolderFCDM = objFSO.BuildPath(strDestFCDM, subfolderFCDM.Name)
  148.             strMsg = folderCompareDateModified (subfolderFCDM.Path, objFSO.BuildPath(strDestFolderFCDM, subfolderFCDM.Name), strMsg)
  149.         Next
  150.     End If
  151.     folderCompareDateModified = strMsg
  152. End Function
  153.  
  154. 'compareAndCopy (oSrc, oDest, dest)
  155. 'Purpose: Copies oSrc to dest if oSrc is newer. 'dest' is the folder that oSrc
  156. '         will be copied into, while oDest is the file/folder that oSrc will be
  157. '         replacing.
  158. 'Returns: N/A
  159. Function compareAndCopy (oSrcCC, oDestCC, destCC)
  160.     'Failsafe (source and destination names must match)
  161.    If Not oSrcCC.Name = oDestCC.Name Then
  162.         WScript.Echo "FAIL: " & oSrcCC.Name & " != " & oDestCC.Name
  163.         WScript.Quit 2
  164.     End If
  165.     dateSrcModified = oSrcCC.DateLastModified
  166.     dateDestModified = oDestCC.DateLastModified
  167.     If dateSrcModified > dateDestModified Or Not oSrcCC.Size = oDestCC.Size Then
  168.         oSrcCC.Copy destCC, True
  169.         Call printCopyInfo(oSrcCC)
  170.     Else
  171.         'WScript.StdOut.Write "."
  172.    End If
  173. End Function
  174.  
  175. 'folderCompareAndCopy (oSrc, oDest, dest)
  176. 'Purpose: Recursive compareAndCopy, by folder
  177. 'Returns: N/A
  178. 'Depends on compareAndCopy
  179. Function folderCompareAndCopy (oSrcFCC, oDestFCC, destFCC)
  180.     'Failsafe (source and destination names must match)
  181.    'WScript.Echo destFCC
  182.    'WScript.Echo "- " & oSrcFCC
  183.    'WScript.Echo "- " & oDestFCC
  184.    If Not oSrcFCC.Name = oDestFCC.Name Then
  185.         WScript.Echo "FAIL: " & oSrcFCC.Name & " != " & oDestFCC.Name
  186.         WScript.Quit 2
  187.     End If
  188.     Set objSubFol = oSrcFCC.SubFolders
  189.     Set objSubFiles = oSrcFCC.Files
  190.     'Recursion end case: individual files
  191.    For Each fileFCC In objSubFiles
  192.         strDestFolder = oDestFCC.Path
  193.         strDestFolder = fixFolderStr(strDestFolder)
  194.         strDestFile = objFSO.BuildPath(oDestFCC.Path, fileFCC.Name)
  195.         If Not objFSO.FileExists(strDestFile) Then
  196.             objFSO.CreateTextFile strDestFile
  197.         End If
  198.         Set objDestFile = objFSO.GetFile(strDestFile)
  199.         Call compareAndCopy(fileFCC, objDestFile, strDestFolder)
  200.     Next
  201.     'Recurse through all subfolders
  202.    For Each subfolderFCC In objSubFol
  203.         'WScript.Echo VBTab & oSrcFCC.Name & "->" & subfolderFCC.Name
  204.        'WScript.Echo VBTab & subfolderFCC.ParentFolder.Name & "->" & subfolderFCC.Name
  205.        strDestFolder = objFSO.BuildPath(oDestFCC.Path, subfolderFCC.Name)
  206.         If Not objFSO.FolderExists(strDestFolder) Then
  207.             objFSO.CreateFolder(strDestFolder)
  208.         End If
  209.         Set objDestFolder = objFSO.GetFolder(strDestFolder)
  210.         Call folderCompareAndCopy(subfolderFCC, objDestFolder, oDestFCC.Path)
  211.     Next
  212. End Function
  213.  
  214. 'fixFolderStr (folder)
  215. 'Purpose: Put a trailing \ on the folder path if it's missing
  216. 'Returns: The correctrd path string
  217. Function fixFolderStr (folder)
  218.     If Not Mid(folder,Len(folder),1) = "\" Then
  219.         fixFolderStr = folder & "\"
  220.     Else
  221.         fixFolderStr = folder
  222.     End If
  223. End Function
  224.  
  225. '---MAIN FUNCTION START---
  226.  
  227. Set args = WScript.Arguments
  228. DTab = VBTab & VBTab
  229. TTab = VBTab & VBTab & VBTab
  230. badAnswer = True
  231. newFiles = False
  232. strHeader = "Name" & TTab & "Source Date"& TTab & "Destination Date"
  233. strNewFileList = ""
  234. intInterval = 5
  235.  
  236. 'Print the usage statement
  237. If Not (WScript.Arguments.Count = 2 Or WScript.Arguments.Count = 3) Then
  238.     WScript.Echo ""
  239.     WScript.Echo "Usage: cscript liveBackup.vbs <source> <destination> [interval]"
  240.     WScript.Echo ""
  241.     WScript.Echo "Checks the source every {interval} seconds for changes, and copies changed"
  242.     WScript.Echo "files to the destination.  Folder hierarchies are preserved."
  243.     WScript.Echo ""
  244.     WScript.Echo "Arguments:"
  245.     WScript.Echo "source      - the source directory or file to be backed up"
  246.     WScript.Echo "destination - the destination directory where the backup will be saved"
  247.     WScript.Echo "interval    - the frequency (in seconds) at which the script will check"
  248.     WScript.Echo "              for changes in the source (default: 5)"
  249.     WScript.Quit 1
  250. End If
  251.  
  252. strSource = args(0)
  253. strDest = args(1)
  254.  
  255. If WScript.Arguments.Count = 3 Then
  256.     If IsNumeric(args(2)) Then
  257.         intInterval = args(2)
  258.     Else
  259.         WScript.Echo "The supplied interval is not a number."
  260.         WScript.Echo "Using the default interval of 5 seconds."
  261.     End If
  262. End If
  263.  
  264. Set objFSO = CreateObject("Scripting.FileSystemObject")
  265.  
  266. If objFSO.FolderExists(strDest) Then
  267.     Set objDest = objFSO.GetFolder(strDest)
  268.     If objFSO.FolderExists(strSource) Then
  269.         'Directory backup mode
  270.        isFileOp = False
  271.         Set objDest = objFSO.GetFolder(strDest)
  272.         Set objSource = objFSO.GetFolder(strSource)
  273.         Set objChildren = objSource.SubFolders
  274.         Set objFiles = objSource.Files
  275.         'Check for new folders in the destination
  276.        For Each subfolder In objChildren
  277.             strDestFolder = objFSO.BuildPath(strDest, subfolder.Name)
  278.             strNewFileList = folderCompareDateModified (subfolder.Path, strDestFolder, strNewFileList)
  279.         Next
  280.         'Check for new files in the destination
  281.        For Each file In objFiles
  282.             strDestFile = objFSO.BuildPath(strDest, file.Name)
  283.             strNewFileList = compareDateModified (strSource, strDestFile, strNewFileList)
  284.         Next
  285.         'If there are newer folders/files in the dest, print list
  286.        If Not strNewFileList = "" Then
  287.             WScript.Echo strHeader
  288.             WScript.Echo strNewFileList
  289.             WScript.Echo "The above files are newer at the destination then at the source."
  290.             WScript.Echo "You will lose any changes you have made to the destination files"
  291.             WScript.Echo "if you choose to continue."
  292.             WScript.Echo ""
  293.             WScript.StdOut.Write "Would you like to continue anyway? [y/n] > "
  294.             strAnswer = ynAnswer()
  295.             If strAnswer = "n" Then
  296.                 WScript.Quit 0
  297.             End If
  298.         End If
  299.         'Put a trailing \ on the destination path if it's missing
  300.        strDest = fixFolderStr(strDest)
  301.         'Confirm the operation
  302.        Call confirmOp(strSource, strDest, isFileOp)
  303.         'Do the initial copy
  304.        For Each subfolder In objChildren
  305.             subfolder.Copy strDest, True
  306.         Next
  307.         For Each file In objFiles
  308.             file.Copy strDest, True
  309.         Next
  310.         WScript.Echo "The script is now actively backing up your files."
  311.         WScript.Echo "Press ^C to stop."
  312.         'MAIN BACKUP LOOP (directory mode)
  313.        While True
  314.             For Each subfolder In objChildren
  315.                 strDestFolder = objFSO.BuildPath(strDest, subfolder.Name)
  316.                 If Not objFSO.FolderExists(strDestFolder) Then
  317.                     objFSO.CreateFolder(strDestFolder)
  318.                 End If
  319.                 Set objDestFolder = objFSO.GetFolder(strDestFolder)
  320.                 Call folderCompareAndCopy(subfolder, objDestFolder, strDest)
  321.             Next
  322.             For Each file In objFiles
  323.                 strDestFile = objFSO.BuildPath(strDest, file.Name)
  324.                 If Not objFSO.FileExists(strDestFile) Then
  325.                     objFSO.CreateTextFile strDestFile
  326.                 End If
  327.                 Set objDestFile = objFSO.GetFile(strDestFile)
  328.                 Call compareAndCopy(file, objDestFile, strDest)
  329.             Next
  330.             'WScript.StdOut.Write "."
  331.            WScript.Sleep(1000 * intInterval)
  332.         WEnd
  333.        
  334.     ElseIf objFSO.FileExists(strSource) Then
  335.         'File backup mode
  336.        isFileOp = True
  337.         Set objSource = objFSO.GetFile(strSource)
  338.         strFilename = objSource.Name
  339.         strDestFile = objFSO.BuildPath(strDest, strFilename)
  340.         'Check for a newer file in the destination
  341.        strNewFileList = compareDateModified (strSource, strDestFile, strNewFileList)
  342.         If Not strNewFileList = "" Then
  343.             'Destination file is newer than the source
  344.            WScript.Echo strHeader
  345.             WScript.Echo strNewFileList
  346.             WScript.Echo "The above files are newer at the destination then at the source."
  347.             WScript.Echo "You will lose any changes you have made to the destination files"
  348.             WScript.Echo "if you choose to continue."
  349.             WScript.Echo ""
  350.             WScript.StdOut.Write "Would you like to continue anyway? [y/n] > "
  351.             strAnswer = ynAnswer()
  352.             If strAnswer = "n" Then
  353.                 WScript.Quit 0
  354.             End If
  355.         End If
  356.         'Put a trailing \ on the destination path if it's missing
  357.        strDest = fixFolderStr(strDest)
  358.         'Confirm the operation
  359.        Call confirmOp(strSource, strDest, isFileOp)
  360.         'Do the initial copy
  361.        objSource.Copy strDest, True
  362.         Set objDestFile = objFSO.GetFile(strDestFile)
  363.         WScript.Echo "The script is now actively backing up your files."
  364.         WScript.Echo "Press ^C to stop."
  365.         'MAIN BACKUP LOOP (file mode)
  366.        While True
  367.             Call compareAndCopy(objSource, objDestFile, strDest)
  368.             'WScript.StdOut.Write "."
  369.            WScript.Sleep(1000 * intInterval)
  370.         WEnd
  371.     End If
  372. Else
  373.     WScript.Echo "The destination directory does not exist or is not a directory."
  374.     WScript.Echo strDest
  375.     WScript.Quit 1
  376. End If
Add Comment
Please, Sign In to add comment