Skip to content

Instantly share code, notes, and snippets.

@aplocher
Last active April 26, 2016 13:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aplocher/d2b8f7607f20ab9839ddd1ec8b20f1e7 to your computer and use it in GitHub Desktop.
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
@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