'Updates existing files in a tree from another tree. The two trees do NOT 
'have to have the same structure.

Option Explicit

Main

Sub Main
Dim fs, strSourceStartFolder, strDestStartFolder
	If WScript.Arguments.Count = 0 Then
		If MsgBox("Updates existing files in a ""destination"" tree (folders and subfolders) with more recent files found in a ""source"" tree. The two trees don't have to share the same structure! Proceed?", vbYesNo, "Proceed") = vbNo Then Exit Sub
	End If
	Set fs = CreateObject("Scripting.FileSystemObject")
	'Get the source folder
	If WScript.Arguments.Named.Exists("source") Then
		strSourceStartFolder = WScript.Arguments.Named.Item("source")
	Else
		strSourceStartFolder = BrowseForFolder("SOURCE FOLDER (Or use the /source argument like " & vbCrLf & WScript.ScriptName & " /source:""C:\Some Folder"")")
	End If
	If strSourceStartFolder = "" Then Exit Sub
	If Not fs.FolderExists(strSourceStartFolder) Then Exit Sub
	'Get the destination folder
	If WScript.Arguments.Named.Exists("dest") Then
		strDestStartFolder = WScript.Arguments.Named.Item("dest")
	Else
		strDestStartFolder = BrowseForFolder("DESTINATION FOLDER (Or use the /dest argument like " & vbCrLf & WScript.ScriptName & " /dest:""C:\Some Folder"")")
	End If
	If strDestStartFolder = "" Then Exit Sub
	If Not fs.FolderExists(strDestStartFolder) Then Exit Sub
	'Update the destination tree with files from the source tree
	UpdateTree strDestStartFolder, strSourceStartFolder
End Sub


Sub UpdateTree(strDestStartFolder, strSourceStartFolder)
Dim fs, fil, fils, fol, fols, ofol, strSourceFile
	Set fs = CreateObject("Scripting.FileSystemObject")
	Set ofol = fs.GetFolder(strDestStartFolder)
	'Check each file in the destination folder
	On Error Resume Next
	Err.Clear
	Set fils = ofol.Files
	If Err.Number <> 0 Then Exit Sub
	For Each fil In fils
		strSourceFile = FindFile(fil.Name, strSourceStartFolder)
		If strSourceFile <> "" Then
			If fil.DateLastModified < fs.GetFile(strSourceFile).DateLastModified Then
				'Use the newer source file to overwrite the old destination file.
				fs.CopyFile strSourceFile, fil.Path, True
				Status strSourceFile & vbCrLf & "    >>>  " & fil.Path
			End If
		End If
	Next
	'Check for any sub folders and recursively process them
	Set fols = ofol.SubFolders
	For each fol in fols
		If Lcase(fol.Name) <> "recycled" Then
			UpdateTree fol.Path, strSourceStartFolder
		End If
	Next
End Sub


Function FindFile(strFileName, strStartPath)
Dim fs, fil, fils, fol, fols, ofol, strFound
	Set fs = CreateObject("Scripting.FileSystemObject")
	Set ofol = fs.GetFolder(strStartPath)
	'Check each file in the folder
	'On Error Resume Next
	Err.Clear
	Set fils = ofol.Files
	If Err.Number = 0 Then 
		For Each fil In fils
			If Lcase(fil.Name) = Lcase(strFileName) Then
				'Return the path to the file
				FindFile = fil.Path
				Exit Function
			End If
		Next
	End If
	'Check for any sub folders and recursively process them
	Set fols = ofol.SubFolders
	For each fol in fols
		If Lcase(fol.Name) <> "recycled" Then
			strFound = FindFile(strFileName, fol.Path)
			If strFound <> "" Then
				FindFile = strFound
				Exit Function
			End If
		End If
	Next
	'Return an empty result if the file isn't found
	FindFile = ""
End Function

Sub Status(strMessage)
	If Lcase(Right(Wscript.FullName, 12)) = "\cscript.exe" Then
		Wscript.Echo strMessage
	End If
End Sub

Function BrowseForFolder(strPrompt)
'Uses the "Shell.Application" (only present in Win98 and newer)
'to bring up a file/folder selection window. Falls back to an
'ugly input box under Win95.
Const ssfDRIVES = 17 'My Computer
Const SFVVO_SHOWALLOBJECTS = 1
Const SFVVO_SHOWEXTENSIONS = 2 
	Dim sh, fol, fs, lngView, strPath
	Set sh = CreateObject("Shell.Application")
	If Instr(TypeName(sh), "Shell") = 0 Then
		BrowseForFolder = InputBox(strPrompt, "Select Folder", CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName))
		Exit Function
	End If
	Set fs = CreateObject("Scripting.FileSystemObject")
	lngView = SFVVO_SHOWALLOBJECTS Or SFVVO_SHOWEXTENSIONS
	strPath = ""
	Set fol = sh.BrowseForFolder(&0, strPrompt, lngView, ssfDRIVES)
	Err.Clear
	On Error Resume Next
	strPath = fol.ParentFolder.ParseName(fol.Title).Path
	'An error occurs if the user selects a drive instead of a folder
	If Err.Number <> 0 Then
		BrowseForFolder = Left(Right(fol.Title, 3), 2) & "\"
	Else
		BrowseForFolder = strPath
	End If
End Function


