Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two-way folder sync with robocopy

Tags:

batch-file

So I've been trying to write a batch file which will sync my local Google Drive folder with my flash drive when I run it. Since robocopy is a one-way process, I set up my code so it asks you whether you want to either sync TO Google Drive or FROM Google Drive. This is so that regardless of which of the two locations I make or edit something, I can always sync the newest version onto both locations.

Before anything happens, the code also verifies that it's plugged into my computer and not someone else's by checking its name.

This is what my code looks like right now:

@echo off
If "%computername%"=="JAKE-PC" (
color 02
set /P c=Sync TO or FROM Google Drive[T/F]?

:choice
if /I "%c%" EQU "T" goto :to
if /I "%c%" EQU "F" goto :from
goto :choice

:to
echo Syncing to Google Drive...
robocopy ".\Google Drive\ " "C:\Users\Jake\Google Drive\ " * /mir /xo
goto :done

:from
echo Syncing from Google Drive...
robocopy "C:\Users\Jake\Google Drive\ " ".\Google Drive\ " * /mir /xo
goto :done

:done
echo Sync Complete.               
pause
)

If NOT "%computername%"=="JAKE-PC" (
color 04
echo Not Jake's PC!
pause
)

It seems to work okay. If I make a change on the flash drive, I run the batch file and type T which will sync my changes to Google Drive. If I make a change on Google Drive, I type F which will sync changes from Google Drive.

There's only one flaw however, and that's if each location has new content to sync. If I create "a.txt" on my flash drive and "b.txt" on Google Drive, and then if I:

-sync TO Google Drive, a.txt is copied to Google Drive from my flash drive but b.txt is gone from both.

-sync FROM Google Drive, b.txt is copied to my flash drive from Google Drive but a.txt is gone from both.

So this causes the problem of files being lost forever if there's new content on both locations. Is there any way to fix this? I just need a two-way method of syncing both locations without the possibility of losing files/folders from one of them. Maybe even without robocopy.

like image 382
Jake Castro Avatar asked Jan 08 '23 10:01

Jake Castro


1 Answers

As per ROBOCOPY /? (or ROBOCOPY.exe doc), /MIR option forces implicite /PURGE:

  /MIR : MIRror a directory tree - equivalent to /PURGE plus all subfolders (/E)
/PURGE : Delete destination files/folders that no longer exist in source.
   /XO : eXclude Older - if destination file exists and is the same date or newer
                         than the source - don’t bother to overwrite it.
    /E : Copy Subfolders, including Empty Subfolders.

Use /E instead of /MIR option and perform copy in both ways unattended:

@echo off

If "%computername%"=="JAKE-PC" goto :sync
color 04
echo Not Jake's PC!
goto :done

:sync
color 02

:to
echo Syncing to Google Drive...
robocopy ".\Google Drive\\" "C:\Users\Jake\Google Drive\\" * /E /XO

:from
echo Syncing from Google Drive...
robocopy "C:\Users\Jake\Google Drive\\" ".\Google Drive\\" * /E /XO

echo Sync Complete.               

:done
pause

Or something similar to next code snippet (keeping set /P user's interpelation):

@echo off
SETLOCAL EnableExtensions
If "%computername%"=="JAKE-PC" goto :sync
color 04
echo Not Jake's PC!
goto :done

:to
echo Syncing to Google Drive...
robocopy ".\Google Drive\\" "C:\Users\Jake\Google Drive\\" * /E /XO
goto :eof

:from
echo Syncing from Google Drive...
robocopy "C:\Users\Jake\Google Drive\\" ".\Google Drive\\" * /E /XO
goto :eof

:sync
color 02
set /P c=Sync TO or FROM Google Drive or BOTH or NOTHING [T/F/B/N]?
if /I "%c%" EQU "T" ( call :to
  goto :done  
)
if /I "%c%" EQU "F" ( call :from
  goto :done  
)
if /I "%c%" EQU "B" (
  call :to
  call :from
  goto :done  
)
if /I not "%c%" EQU "N" goto :sync
echo No Sync 

:done
echo Sync Complete.               
pause

Note that if Command Extensions are disabled GOTO will no longer recognise the :EOF label (use exit /B instead of goto :EOF in the case). Although Command Extensions are enabled by default, we can't presume in it. That's why I use SETLOCAL EnableExtensions as a matter of general principle.

If Command Extensions are enabled GOTO changes as follows:

GOTO command now accepts a target label of :EOF which transfers control to the end of the current batch script file. This is an easy way to exit a batch script file without defining a label.

Type CALL /? for a description of extensions to the CALL command that make this feature useful.

Also note that Using GOTO within parentheses - including FOR and IF commands - will break their context.

like image 106
JosefZ Avatar answered Jan 14 '23 15:01

JosefZ