Jump to content
MSFN is made available via donations, subscriptions and advertising revenue. The use of ad-blocking software hurts the site. Please disable ad-blocking software or set an exception for MSFN. ×

Need help with a batch script using robocopy...


Recommended Posts

I won't bore you with the details, just know that this has to be a BATCH SCRIPT (I can't do this using another language or program and achieve the desired affect).

Here's my current script:


@echo off

:: Defaults:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: Backup 01
set _sourcedir01=C:\temp\copy1
set _destdir01=H:\Backups\
set _options01=/MIR /XJ /NJH /NDL /NJS /NS /NC /R:1 /W:10

:: Confirmation:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
echo -------------------------------------------------------------------------------
echo Backup Script:
echo -------------------------------------------------------------------------------
echo.
echo Backup Source folder(s):
echo ------------------------
echo [%_sourcedir01%]
echo.
echo Backup Destination folder(s):
echo -----------------------------
echo [%_destdir01%]
echo.
echo Press CTRL+C at any time to stop the transfer.
echo.
set /p continue=Proceed? (Y/N):
if /i %continue%==N goto _end

:: Run Backup Job
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cls
echo.
echo Updating [%_destdir01%]:
robocopy "%_sourcedir01%" "%_destdir01%" %_options01%

goto _end

:: Exit:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:_end
echo.
echo Backup job complete, press any key to exit...
pause > nul

So simple and it works right? Here's my problem. I need to somehow tweak this so that I can copy to multiple destinations. Now I know I could just create a new variable for each destination and then run each variable through this own robocopy command, but I'm thinking there has to be an easier way to do that and reuse code. I understand batch scripts can't do arrays, but I'm thinking something similar is what I need. Here's some pseudocode that (I hope) illustrates my goal:


@echo off

:: Defaults:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: Backup 01
set _sourcedir=C:\temp\copy1
set _destdir="'H:\Backups\', 'F:\Backup Drive\', 'E:\Backup_2'"
set _options=/MIR /XJ /NJH /NDL /NJS /NS /NC /R:1 /W:10

:: Run Backup Job
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
loop through values in %_destdir%
robocopy "%_sourcedir%" "%_destdir%" %_options%
end loop

As you can see from the above pseudocode all I really want to do is somehow set up a series of directory paths and pass each one through to my %_desdir% variable in sequence. My intended solution also needs to support spaces in directory paths. Does anyone know how to do this?

Link to post
Share on other sites

A simple for could the job. Check the for /? from a dos box for with /F and delims=, and usebackq. To space in directory names, you already did it correctly you just need to to double quote the variable when using it and not when setting it.

Link to post
Share on other sites

I hope this suits your purpose!

@echo off:: Defaults:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Set variablesset _sourcedir=C:\temp\copy1set _options=/MIR /XJ /NJH /NDL /NJS /NS /NC /R:1 /W:10set _destlist=H:\Backups "F:\Backup Drive" E:\Backup_2:: Loop through list of destination directoriesfor %%# in (%_destlist%) do call :_continue %%~#:: Exit:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::_endecho=echo=Backup job complete, press any key to exit...pause>nulgoto :eof:: Confirmation:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::_continueset _destdir=%*clsecho=-------------------------------------------------------------------------^------echo=Backup Script:echo=-------------------------------------------------------------------------^------echo=echo=Backup Source folder(s):echo ------------------------echo=[%_sourcedir%]echo=echo Backup Destination folder(s):echo=-----------------------------echo=[%_destdir%]echo=echo=Press CTRL+C at any time to stop the transfer.echo=set/p "continue=Proceed? [Y/N]: "if /i %continue%' neq y' goto :eof:: Run Backup Job:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::clsecho=echo=Updating [%_destdir%]:robocopy "%_sourcedir%" "%_destdir%" %_options%pause
Link to post
Share on other sites

I hope this suits your purpose!

@echo off

:: Defaults:
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Set variables
set _sourcedir=C:\temp\copy1
set _options=/MIR /XJ /NJH /NDL /NJS /NS /NC /R:1 /W:10
set _destlist=H:\Backups "F:\Backup Drive" E:\Backup_2

:: Loop through list of destination directories
for %%# in (%_destlist%) do call :_continue %%~#

:: Exit:
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:_end
echo=
echo=Backup job complete, press any key to exit...
pause>nul
goto :eof

:: Confirmation:
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:_continue
set _destdir=%*
cls
echo=-------------------------------------------------------------------------^
------
echo=Backup Script:
echo=-------------------------------------------------------------------------^
------
echo=
echo=Backup Source folder(s):
echo ------------------------
echo=[%_sourcedir%]
echo=
echo Backup Destination folder(s):
echo=-----------------------------
echo=[%_destdir%]
echo=
echo=Press CTRL+C at any time to stop the transfer.
echo=
set/p "continue=Proceed? [Y/N]: "
if /i %continue%' neq y' goto :eof

:: Run Backup Job
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
cls
echo=
echo=Updating [%_destdir%]:
robocopy "%_sourcedir%" "%_destdir%" %_options%
pause

Awesome, I never realized it could be as simple as putting spaces between the times in my variable declaration. I'll try that and post my final code here for you guys to look at.

Link to post
Share on other sites

This was my final solution, and it seems to work well:

@ECHO OFF

:: Prepare the Command Processor
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION

:: Defaults (directory paths must be in quotes):
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
SET _source="C:\temp\copy 1"
SET _destination="C:\temp\dest 1" "C:\temp\dest 2" "C:\temp\dest 3" "C:\temp\dest 4" "C:\temp\dest 5"
SET _options=/MIR /XJ /NJH /NDL /NJS /NS /NC /R:1 /W:10

:: Customize What Gets Copied
::SET _filelist=
::SET _excludedfiles=/XF
::SET _excludedirs=/XD

:: Confirmation:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO -------------------------------------------------------------------------------
ECHO Robocopy Backup Script:
ECHO -------------------------------------------------------------------------------
ECHO.
ECHO Backup Source:
ECHO --------------
ECHO %_source%
ECHO.
ECHO Backup Destination(s):
ECHO ----------------------
FOR %%G IN (%_destination%) DO ECHO %%G

ECHO.
ECHO Press CTRL+C at any time to abort the backup job.
ECHO -------------------------------------------------------------------------------
SET /P continue=Proceed? (Y/N):
IF /I %continue%==N GOTO _END

:: Run Backup Job
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CLS
ECHO.
ECHO Updating Destination(s):
ECHO ------------------------
FOR %%G IN (%_destination%) DO ECHO. & ECHO -Updating %%G & ROBOCOPY.EXE %_source% %%G %_excludedfiles% %_excludedirs% %_options%
GOTO _END

:: End:
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:_END
ECHO.
ECHO Backup job complete, press any key to exit...
PAUSE > NUL

What do you guys think? See any potential "gotchas" in my code that could cause it to mess up? I guess I'm worried that it seems a bit "rigged" what with all the "&"'s in my FOR loop. Any suggestions to improve it?

Edited by zeusabj
Link to post
Share on other sites

There's nothing really bad there, however some observations:

My code used this line:

if /i %continue%' neq y' goto
...

whereas yours uses:

IF /I %continue%==N GOTO
...

The problem I have with it is that because there's no error trapping on what is user entered, your code will execute the command unless told explicitly not to, mine will only execute it if eplicitly told to do so!

My code allows that the user can choose Y or N for any of the listed destination directories, yours allows for Y or N to ALL or NONE!

There is no requirement to enable delayed expansion in your script so it would be prudent not to do so.

The %_filelist% variable is commented out however it doesn't get a mention anywhere!

It is common practice to use a max 80 character line length for your code, (as I did in the example I provided). It also means that following that convention you'd not have the long For loop with all of the ampersands:

SET _destination="C:\temp\dest 1" "C:\temp\dest 2" "C:\temp\dest 3"
SET _destination=%_destination% "C:\temp\dest 4" "C:\temp\dest 5"

FOR %%# IN (%_destination%) DO (ECHO=&ECHO=-Updating %%G
ROBOCOPY.EXE %_source% %%G %_excludedfiles% %_excludedirs% %_options%)

At the end of your Run Backup Job section you have a GOTO _END statement to go to what is already the next command, it is therefore not required.

Link to post
Share on other sites

Now see, that's why it says "Wise Owl" under your avatar. Seriously, thank you *so* very much for taking the time to write up that reply. That's the exact kind of constructive criticism I have been looking for. I've only been writing batch scripts for about a year now and I'm embarrassed to say there's still a lot I don't understand. Also I'm located in a small town and there aren't many other technical people around, so I rely on the Internet a lot to bounce questions off other technical individuals. Would you believe it took me almost two whole days to come up with that code on my own? If I'd have just had someone local to ASK in the first place, then I thought of MSFN. You guys totally came through for me.

Thank you so much!

Link to post
Share on other sites

Hey Yzöwl, another dumb question. Why did you use "=" after each "echo"? Is there a reason for that or is it just your preferred programming style? Also I've seen other batch scripts that use "goto :eof". Obviously that is used to exit the batch script but you never see the actual ":eof" function anywhere in the script. Is it just implied or could I name it anything (like "goto :nothing"); leave ":nothing" out of my script and have it work the same way?

Edited by zeusabj
Link to post
Share on other sites

Goto :EOF is used as the return in basic => it will go to the next step in the loop calling it.

It is very usefull to create function like in others languages.

Link to post
Share on other sites

@zeusabj

the "special" :EOF tag has been introduced in NT batch (i.e. is NOT available in "pure-DOS" or Windows 9x/Me) it is short for End Of File

http://www.robvanderwoude.com/exit.php

as a complement to the ability to CALL and internal label/subroutine, as well added to NT:

http://www.robvanderwoude.com/call.php

In the context of CALLing a subroutine it is equivalent to the RETURN command used in many languages.

jaclaz

Edited by jaclaz
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...