Skip to content

martin-schell/syncFoldersWIN

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 

Repository files navigation

syncFolders.bat

Synchronize two folders under Windows with robocopy.

Additional features:

  • Optional: If a file, which exists in the target directory, is changed in source directory, then its older version in the target directory will be backed up before it is replaced.
  • Two-way syncing:
    • Any file in the target directory that don't exist in the source directory, will be backed up before it is deleted. A timestamp wil be added to the name of each file that has been backed up.
    • Any empty folders are deleted during the sync process.

Usage

syncFolders.bat source_folder target_folder

The following settings can be configured in the script:

VERBOSE

If this is set to true, then DEBUG logging is enabled (default: false).

BIN

Files in target_folder, which do not exists source_folder, will be moved to BIN before deleting them in target_folder (default: bin). If this directory does not exists, then the script creates it during runtime.

ARCHIVE

Directory to save older version of updated files (default: archive). If this directory does not exists, then the script creates it during runtime.

BACKUP

If this is set to true, then files in target_folder will be copied to ARCHIVE before they will be replaced by newer version in source_folder.

PATH_PATTERNS_IN

File with patterns, separated by newline.

# Example for patterns_in.txt
*.cfg
*.bak

Only files which match these patterns will be copied from source_folder to target_folder.

PATH_PATTERNS_EX

File with patterns, separated by newline.

# Example for patterns_ex.txt
*_template

Files which match these patterns will not be copied from source_folder to target_folder.

Further information

@REM Validate if user passed enough parameters
if "%1"=="" (
    echo Usage: %~nx0 source_folder target_folder
    exit /b 1
)
if "%2"=="" (
    echo Error: Missing second parameter.
    echo Usage: %~nx0 source_folder target_folder
    exit /b 1
)

%~nx0 is a parameter extension for filenames which expands %0 to a file name and extension only (refer to https://ss64.com/nt/syntax-args.html)

%~n0 expands %0 only to file name.

@REM Set timestamp
set hh=%TIME:~0,2%
@REM To prevent syntax error during file operations due to whitespaces, a null is appended if the part of TIME is lower than 10.
if "%hh:~0,1%" == " " set hh=0%hh:~1,1%
set mm=%TIME:~0,2%
if "%mm:~0,1%" == " " set mm=0%mm:~1,1%
set ss=%TIME:~0,2%
if "%ss:~0,1%" == " " set ss=0%ss:~1,1%
set DD=%date:~0,2%
set MM=%date:~3,2%
set YYYY=%date:~6,4%
set dtime=%YYYY%%MM%%DD%_%hh%%mm%%ss%
  • %DATE% contains current date, e.g. 15.05.25
  • %VAR:~n,m% extracts m strings from VAR, beginning from n including n.
  • %TIME% contains the current time in the local format, e. g. 9:23:10,76
  • if "%hh:~0,1%" == " " set hh=0%hh:~1,1

If hour, min etc. is lower than 10, its output with a whitespace e. g. _9 . To prevent syntax error during file operations, the whitespace is replaced by a null.  

@REM Basic checks
if not exist %SOURCE_DIR% (
    echo %SOURCE_DIR% does not exists. Abort script.
    exit /b
)

if not exist %DST_DIR% (
    echo %DST_DIR% does not exists. Abort script.
    exit /b
)
setlocal enabledelayedexpansion
set filters=

@REM Get patterns for sync
for /F %%F in ('type %PATH_PATTERNS_IN%') do (
    set "pat=%%F"
    set "in_patterns=!in_patterns!!pat! "
)
  • setlocal enabledelayedexpansion: Delayed Expansion is necessary for adding values in a variable (refer to https://ss64.com/nt/delayedexpansion.html)
  • The loop iterates through each line in file, stores each value in pat and appends value of pat in in_patterns
  • type is like cat 
  • Result: in_patterns = e.g. *.bat *.cfg 

To execute the loop above directly in the Shell, %%F has to be replaced by %F.

@REM Delete empty folders in target dir
robocopy %DST_DIR% %DST_DIR% /S /MOVE
  • /S skips empty folders
  • /MOVE: Moves files and directories, and deletes them from the source after they're copied.
robocopy %SOURCE_DIR% %DST_DIR% %in_patterns% /MT:32 /LOG+:%LOGFILE% /NDL /NJS /NS /NP /DCOPY:T /S /XF %ex_patterns%
  • /DCOPY:T  - Preserve timestamps
  • /XF - Exclude files based on patterns
  • /S - Copy subdirectories, except of emtpy ones
  • /LOG:+ redirects output in logfile and appends ( + ) entries in logfile.
  • /NLD :  Directory names aren't logged.
  • /NJS : No job summary in log.
  • /NS : File sizes aren't logged.
  • /NP : No log of progress.
  • /MT:32 : To speed up runtime, create multi-threaded copies with 32 threads (default 8)
  • Source: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
for /R %DST_DIR% %%F in (*.*) do (
    set "dst_path=%%~F"
    set "src_path=!dst_path:%DST_DIRNAME%=%SRC_DIRNAME%!"
    
    if not exist !src_path! (
        move "%%F" %BIN%\%dtime%_%%~nxF
    )
)
  • Walks recursively through destination directory and checks, if file exists in source directory.
  • for /R %DST_DIR% %%F in (*.*) loops through all files (*.*) recursively in the %DST_DIR% directory.
  • %%F represents the full path of each file found.
  • dst_path=%%~F stores the fullpath (%%~F) in the variable dst_path.
  • !dst_path:%DST_DIR%=%SRC_DIR%! replaces name of target folder by name of source folder in path of file in target folder.

Example

  • DST_DIR = C:\Users\user\Skripte\syncConf\testdata\test_target\

  • SRC_DIR = C:\Users\user\Skripte\syncConf\testdata\test_glx\

  • SRC_DIRNAME = test_glx

  • DST_DIRNAME = test_target

  • dst_path = C:\Users\user\Skripte\syncConf\testdata\test_target\wildfly\test.cfg

  • src_path → C:\Users\user\Skripte\syncConf\testdata\test_glx\wildfly\test.cfg

  • !src_path! is a delayed expansion 

What is delayed expansion?

Delayed expansion is a feature in batch scripting to safely use and update variables inside loops or conditional blocks (like for, if, etc.) where normal variable expansion like %VAR% would not work as expected.

If a variable changes inside a loop or block, %VAR% will still have the old value (or no value) from before the loop started.

If file does not exists in source directory, it will be moved to the bin directory.

Why /MIR is not used?

To mirror both directories respectively deleting files / folders which do not exist in source folder, do not use /mir in relation with filters
robocopy %SOURCE_DIR% %DST_DIR% /S /MIR /DCOPY:T /MIR /DCOPY:T  deletes files in destination dir which do not exists in source dir
robocopy %SOURCE_DIR% %DST_DIR% /S /MIR "*.cfg" "*.bak" /DCOPY:T /MIR /DCOPY:T  does not delete files in destination dir which do not exists in source dir.

About

Synchronize two folders under Windows.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors