For batch copy purposes I need to create script that I was thinking will be simple, but no luck.
Use case is: Copy all files from sourcedirectory
to targetdirectory
where sourcedirectory file is newer of not exists in targetdirectory, but if file already exists in targetdirectory rename it to original_name.B<timestamp_last_modified>
before copy/overwrite
What I started with:
xcopy %sourcedirectory% %targetdirectory% /f /i /s /h /d /y >> W:\Xcopy%datetimefile%.log 2>&1
But it can not do the rename part so I started playing around and got here:
@echo off
rem configuration
set sourcedirectory="d:\Ice"
set targetdirectory="W:\Ice"
set logdirectory="W:"
rem following part only creates timestamp for log file (datetimefile) and log record (datetimecopy)
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetimefile=%%I
set datetimecopy=%datetimefile:~0,8% %datetimefile:~8,2%:%datetimefile:~10,2%:%datetimefile:~12,2%
set datetimefile=%datetimefile:~0,8%_%datetimefile:~8,6%
set "logfile=%logdirectory:~0,-1%\Backup%datetimefile%.log^""
rem logging
echo Log File is %logfile%
echo ----- BACKUP FROM: %sourcedirectory% TO: %targetdirectory% AT: %datetimecopy% -----
echo ----- BACKUP FROM: %sourcedirectory% TO: %targetdirectory% AT: %datetimecopy% ----- >> %logfile% 2>&1
rem execution
for /F "tokens=*" %%A in ('xcopy %sourcedirectory% %targetdirectory% /f /i /s /h /d /y /l') do (call :subroutine "%%A")
rem log timestam creation and logging
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetimecopy=%%I
set datetimecopy=%datetimecopy:~0,8% %datetimecopy:~8,2%:%datetimecopy:~10,2%:%datetimecopy:~12,2%
echo ----- BACKUP FINISHED AT: %datetimecopy% -----
echo ----- BACKUP FINISHED AT: %datetimecopy% ----- >> %logfile% 2>&1
goto :finish
:subroutine
set "f=%1"
set "f=%f:~1,-1%"
set "filefrom=%f: -> =" & set "fileto=%"
set "filefrom=^"%filefrom%^""
set "fileto=^"%fileto%^""
if NOT EXIST %fileto% GOTO :cpyonly
set "g=%fileto%"
call set "newg=%%g:\=\\%%"
for /f "tokens=2 delims==" %%N in ('wmic datafile where name^=%%newg%% get LastModified /format:list') do set lastmod=%%N
set "i=%fileto%"
set "target="%%~ni%%~xi.B%lastmod:~0,14%^""
echo rename %g% %target%
echo "rename %g% %target%" >> %logfile% 2>&1
rename %g% %target% >> %logfile% 2>&1
goto :cpyonly
:cpyonly
echo "xcopy %filefrom% %fileto% /f /h /d /y" >> %logfile% 2>&1
echo xcopy %filefrom% %fileto% /f /h /d /y
xcopy %filefrom% %fileto% /f /h /d /y >> %logfile% 2>&1
GOTO :finish
rem :testing
rem wmic datafile where name="d:\\CopyFrom\\drziaky.txt" get LastModified /format:list
rem d:\Ice\Private\StartBatch\Backup_new.bat
:finish
However it did not work and can not move forward, the observed issues:
- The filenames contain spaces and it creates splits in the files even when I have used the
"tokens=*"
I have not found a way how to pass the whole%%A
to subroutine - By the file operations I sometimes need to remove or add the "" around, this works on some positions and on some not, again I failed to discover when/why (for example this
set "f=%f:~1,-1%"
is intended to remove " and thisset "fileto=^"%fileto%^""
is intended to add them
To the previous versions (not in this post, but have them on my HDD):
- I tried using copy, but copy did not create target directory
- The
wmic
commands are used because of local differences and seems to work (for getting time and also last modification date) - xcopy as list generator works (small issue with last line listing number of files)
- Parsing tried first via
for /f
and then via theset "filefrom=%f: -> =" & set "fileto=%"
(copied from here) but none works
Below is last working code (with copy) but:
- can not create target directories
- Breaks on spaces in file name
- Breaks on last line of xcopy (X files copied)
Maybe it breaks on some other cases also, but it is the best I managed to get until now, however get stuck and can not move forward from this point, could somebody help me? Thank you and apologize for long post. If it is already here then I'm really blind because have spend lot of hours searching.
PS: enabledelayedexpansion
can not be used :-( Also usage of 3rd parties can not be relyed to so the script can be only 1 file
set sourcedirectory="d:\Ice"
set targetdirectory="W:\Ice"
set logdirectory="W:"
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetimefile=%%I
set datetimecopy=%datetimefile:~0,8% %datetimefile:~8,2%:%datetimefile:~10,2%:%datetimefile:~12,2%
set datetimefile=%datetimefile:~0,8%_%datetimefile:~8,6%
set "logfile=%logdirectory:~0,-1%\Backup%datetimefile%.log^""
echo ----- BACKUP FROM: %sourcedirectory% TO: %targetdirectory% AT: %datetimecopy% ----- >> %logfile% 2>&1
for /f "tokens=1,3" %%A in ('xcopy %sourcedirectory% %targetdirectory% /f /i /s /h /d /y /l') do (call :subroutine "%%A" "%%B")
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetimecopy=%%I
set datetimecopy=%datetimecopy:~0,8% %datetimecopy:~8,2%:%datetimecopy:~10,2%:%datetimecopy:~12,2%
echo ----- BACKUP FINISHED AT: %datetimecopy% ----- >> %logfile% 2>&1
goto :eof
:subroutine
set "f=%1"
if NOT EXIST %2 GOTO :cpyonly
set "g=%2"
call set "newg=%%g:\=\\%%"
for /f "tokens=2 delims==" %%N in ('wmic datafile where name^=%%newg%% get LastModified /format:list') do set lastmod=%%N
set "target="%~n2%~x2.B%lastmod:~0,14%^""
echo "rename %g% %target%" >> %logfile% 2>&1
rename %g% %target% >> %logfile% 2>&1
goto :cpyonly
:cpyonly
echo "copy %1 %2" >> %logfile% 2>&1
copy %1 %2 >> %logfile% 2>&1
GOTO :eof
:eof