Last active
April 26, 2016 13:39
-
-
Save aplocher/d2b8f7607f20ab9839ddd1ec8b20f1e7 to your computer and use it in GitHub Desktop.
Sync two folders using VSS. Handy for syncing source code with a backup destination on OneDrive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@echo off & setlocal enabledelayedexpansion | |
:: Backup.bat: | |
:: Adam Plocher - gist.github.com/aplocher - bitcollectors.com | |
:: | |
:: --Description: | |
:: Synchronize (backup) a directory to another dir using VSS (volume shadow copy | |
:: service) in Windows to help ensure a successful copy without locked files | |
:: impeding the process. | |
:: | |
:: Can be called from command line or can be used to install a scheduled task | |
:: that runs a regular backup when the machine is idle. An example of where this | |
:: is useful is keeping sourcecode regularly backed up on OneDrive. | |
:: | |
:: Configure the variables below or pass in command line args | |
:: | |
:: --Requirements: | |
:: SHADOWSPAWN.EXE - Executable can be obtained at | |
:: github.com/aplocher/shadowspawn/releases | |
:: | |
:: ============================================================================ | |
:: EDIT THE FOLLOWING CONFIGURATION VALUES | |
:: ============================================================================ | |
:: The source directory path to backup | |
set "_sourcePath=C:\SOURCE" | |
:: The destination directory path in which to backup to | |
set "_destinationPath=%USERPROFILE%\OneDrive2\OneDrive\Backup\SourceSync" | |
:: Path to shadowspawn.exe. Avail at github.com/aplocher/shadowspawn/releases | |
:: I take no credit for this app, Just hosting the releases. Project by candera | |
set "_pathToShadowSpawn=C:\TEMP\SHADOWSPAWN.EXE" | |
:: ShadowSpawn will create a temporary drive letter. Make sure you pick one | |
:: that's available! Do NOT include trailing slash | |
set "_tempDriveLetter=S:" | |
:: Output destination of robocopy log. If you don't know or care, leave in TEMP | |
set "_roboCopyLog=%TEMP%\sourceBackup.txt" | |
:: File and Directory exclusions | |
set "_excludeFiles=*.7z *.zip *.suo .gitignore .gitattributes" | |
set "_excludeDirs=.git node_modules $tf .vs" | |
:: ============================================================================ | |
:: STOP | |
:: ============================================================================ | |
set "_currentBatFile=%~f0" | |
set "_isInteractive=1" | |
pushd %~dp0 | |
title Shadow Backup | |
call :isRunningAsAdmin isAdmin | |
if [%isAdmin%]==[0] ( | |
echo Error, you must run this as an administrator | |
goto :done | |
) | |
set "lastAction=" | |
for %%x in (%*) do ( | |
if /i [!lastAction!]==[pathToShadowSpawn] ( | |
echo !lastAction! %%x | |
set "lastAction=" | |
set "_pathToShadowSpawn=%%x" | |
) | |
if /i [!lastAction!]==[destinationPath] ( | |
echo !lastAction! %%x | |
set "lastAction=" | |
set "_destinationPath=%%x" | |
) | |
if /i [!lastAction!]==[sourcePath] ( | |
echo !lastAction! %%x | |
set "lastAction=" | |
set "_sourcePath=%%x" | |
) | |
if /i [%%x]==[/pathToShadowSpawn] (set "lastAction=pathToShadowSpawn") | |
if /i [%%x]==[/destinationPath] (set "lastAction=destinationPath") | |
if /i [%%x]==[/sourcePath] (set "lastAction=sourcePath") | |
if /i [%%x]==[/installTask] (set "_mode=INSTALL") | |
if /i [%%x]==[/install] (set "_mode=INSTALL") | |
if /i [%%x]==[/uninstallTask] (set "_mode=UNINSTALL") | |
if /i [%%x]==[/uninstall] (set "_mode=UNINSTALL") | |
if /i [%%x]==[/sim] (set "_mode=SIM") | |
if /i [%%x]==[/run] (set "_mode=RUN") | |
if /i [%%x]==[/fromTask] ( | |
set "_isInteractive=0" | |
set "_mode=RUN" | |
) | |
) | |
if [%_mode%]==[SIM] (goto :sim) | |
if [%_mode%]==[RUN] (goto :run) | |
if [%_mode%]==[INSTALL] (goto :install) | |
if [%_mode%]==[UNINSTALL] (goto :uninstall) | |
goto :help | |
:sim | |
echo --MODE: RUN [SIMULATION] | |
call :getCommand result "%_pathToShadowSpawn%" "%_sourcePath%" "%_destinationPath%" "%_tempDriveLetter%" "%_roboCopyLog%" "%_excludeFiles%" "%_excludeDirs%" | |
%result% /TEE /L | |
goto :done | |
:run | |
echo --MODE: RUN [THIS IS THE REAL DEAL] | |
call :getCommand result "%_pathToShadowSpawn%" "%_sourcePath%" "%_destinationPath%" "%_tempDriveLetter%" "%_roboCopyLog%" "%_excludeFiles%" "%_excludeDirs%" | |
%result% | |
goto :done | |
:install | |
SCHTASKS.EXE /CREATE /RU SYSTEM /SC ONIDLE /I 5 /TN "SourceBackup" /TR "%_currentBatFile% /FROMTASK /PATHTOSHADOWSPAWN %_pathToShadowSpawn% /DESTINATIONPATH %_destinationPath% /SOURCEPATH %_sourcePath%" | |
goto :done | |
:uninstall | |
SCHTASKS.EXE /DELETE /TN "SourceBackup" | |
goto :done | |
:help | |
echo This script will synchronize two folders using VSS. | |
echo. | |
echo It is recommended that you update default values directly in this script | |
echo in your favorite text editor. | |
echo. | |
echo MAKE SURE YOU HAVE EDITED AND CONFIGURED THIS SCRIPT BEFORE RUNNING | |
echo A SYNCHRONIZATION | |
echo. | |
echo /SIM - run a simulation. No files will be copied | |
echo ex: %~nx0 /sim | |
echo. | |
echo /RUN - manually run synchronization from command line | |
echo ex: %~nx0 /run | |
echo. | |
echo /INSTALLTASK - install a task that will run whenever the PC is idle | |
echo ex: %~nx0 /installTask | |
echo. | |
echo /UNINSTALLTASK - uninstall the task | |
echo ex: %~nx0 /uninstallTask | |
echo. | |
echo /PATHTOSHADOWSPAWN - path the shadowspawn.exe | |
echo ex: %~nx0 /sim /pathToShadowSpawn "C:\temp\shadowspawn.exe" | |
echo. | |
echo /DESTINATIONPATH - path to output sync folder | |
echo ex: %~nx0 /sim /destinationPath "%USERPROFILE%\OneDrive\Backup\SourceCode" | |
echo. | |
echo /SOURCEPATH - path to the folder to be synchronized from | |
echo ex: %~nx0 /sim /sourcePath "C:\SourceCode" | |
echo. | |
goto :done | |
:done | |
echo. | |
if [%_isInteractive%]==[1] (pause) | |
endlocal | |
echo. | |
goto :eof | |
:: --FUNCTIONS-- | |
:isRunningAsAdmin | |
setlocal | |
set "result=0" | |
net file >nul 2>&1 | |
if [%ERRORLEVEL%]==[0] (set "result=1") | |
endlocal & set "%~1=%result%" | |
goto :eof | |
:getCommand | |
setlocal | |
set "pathToShadowSpawn=%~2" | |
set "sourcePath=%~3" | |
set "destinationPath=%~4" | |
set "tempDriveLetter=%~5" | |
set "roboCopyLog=%~6" | |
set "excludeFiles=%~7" | |
set "excludeDirs=%~8" | |
echo -- %pathToShadowSpawn% | |
echo -- %sourcePath% | |
echo -- %destinationPath% | |
echo BACKUP AT %DATE% - %TIME% > %roboCopyLog% | |
echo -- %pathToShadowSpawn% >> %roboCopyLog% | |
echo -- %sourcePath% >> %roboCopyLog% | |
echo -- %destinationPath% >> %roboCopyLog% | |
set "result=%pathToShadowSpawn% %sourcePath% %tempDriveLetter% ROBOCOPY %tempDriveLetter%\ %destinationPath% /MIR /XO /FFT /XF %excludeFiles% /XD %excludeDirs% /LOG:%roboCopyLog%" | |
echo -- CMD: %result% >> %roboCopyLog% | |
endlocal & set "%~1=%result%" | |
goto :eof |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment