Speed Up Xcopy in Batch - windows

So I'm trying to copy a backup of the data from my app. I wrote the batch script below to do this, but the script takes forever to run.
I start the batch script at 1am, and it is still running at 8:30am. This seems weird to me because when I copy the backup of my app manually in Windows File Explorer, it copies in 7-15 minutes depending on network traffic.
I REM the %backupcmd% "C:\Program Files\App\App Server\Data\Backups" "%drive%\" line. That was the original line of batch script I used to backup the data, and it worked efficiently up till a month ago.
So I tried the xcopy command with /d, so it would only copy source files that have been changed on or after that date (the current date), and the backups I'm copying are made at 12:01am every night and the copy backup script starts at 1am.
Any advice as to how to speed up my xcopy would be appreciated. If you think I should use powershell for this task too, I'm open to that option as well.
#echo off
for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE 2^>NUL`) do if '.%%i.'=='.LocalDateTime.' set ldt=%%j
set yyyy=%ldt:~0,4%
set mm=%ldt:~4,2%
set dd=%ldt:~6,2%
:: variables
set drive=Z:\RootSoft\App\Data Backups
set backupcmd=xcopy /s /c /d /e /h /i /r /y /f /z
echo ### Backing up Backup...
REM %backupcmd% "C:\Program Files\App\App Server\Data\Backups" "%drive%\"
xcopy "C:\Program Files\App\App Server\Data\Backups" "Z:\RootSoft\App\Data Backups" /D:%mm%-%dd%-%yyyy% /s /c /e /h /i /r /y /f /z
:: use below syntax to backup other directories...
:: %backupcmd% "...source directory..." "%drive%\...destination dir..."
echo Backup Complete!
echo %errorlevel%
pause

You could try with ROBOCOPY and /MT switch which could accelerate the copy.
Also you can make some test by measuring the during process with TimeThis that can be found here (no need to be installed, just extract the exe with 7z in the current batch file folder)

netsh interface tcp show global
netsh int tcp set heuristics disabled
netsh int tcp set global autotuninglevel=disabled
netsh int ip set global taskoffload=disabled

Related

How to create a fake/dummy Windows tree from other Windows tree with Windows shell?

I have a big Windows directory and file tree. Now I need to copy this tree to another location but I do not want to copy the contents from each file. Only the structure and filenames with 0 bytes contents are needed. How could this be done with as cmd shell in Windows 10?
What I did:
xcopy /t e:\oldtreedir e:\new\oldtreedir
dir /a /b /s > mybat.bat
edit mybat.bat to:
replace \ne:\ to
\ncopy nul e:\new\
so that it is for each filename the line
copy nul e:\new\oldtreedir\file1.txt
I had to edit the mybat.bat. Could this be done by a script in the Windows command line?
PS: I found this: WIN-PRg but this program do not create a dir-tree. All files are in one dir only.
If I got your question right, robocopy should do the trick:
robocopy "E:\oldtreedir" "E:\new\oldtreedir" "*.*" /E /CREATE
No need to create an additonal batch file:
#echo off
setlocal enabledelayedexpansion
xcopy /t e:\oldtreedir e:\new\oldtreedir
for /f %%a in ('dir /b /s /a-d "e:\oldtreedir\*"') do (
set "file=%%a"
set "file=!file:E:\=E:\new\!"
break>"!file!"
)

How to delete *.bak files recursively older than a specific date depending on directory in file path?

I'm writing a batch file for Windows 7.
I currently have a code that deletes old backups from our masters folders within our site management folders. This is the code:
for /d %%A in ("Y:\*.*") do del /s /q /f "%%A\masters\*.bak"
However I need to code it to only delete things that are older than 3 years, which would be this code:
forfiles /P "Y:\" /S /D -1096 /M *.bak /C "cmd /C del #path"
However I need what is in the top code so that I can delete all *.bak files from the masters folders that exist within our 173 site management folders. I'm ripping my hair out figuring this out. I can't have it deleting *.bak files from our other folders.
I've tried combining the code, but below command line in batch file does not work as expected:
forfiles /S /D -1096 /M *.bak /C "cmd /C for /d %%A in ("Y:\*.*") do del /s /q /f "%%A\masters\*.bak"
How to delete all *.bak files older than 3 years anywhere in directory tree if second directory in file path is masters and keep all other *.bak files being newer or in a directory where second directory in file path is not masters?
Create first a batch file C:\Temp\DeleteBackup.bat with the following commands:
#echo off
set "BackupFileName=%~1"
if not "%BackupFileName:\masters\=%" == "%BackupFileName%" ECHO del "%BackupFileName%"
This batch code checks if the file name with full path and file extension contains anywhere \masters\ by removing this string case-insensitive from left argument of string comparison.
If the remaining string is not equal the unmodified file name string because of containing \masters\ in path, the IF condition is true and the backup file would be deleted if there would not be command ECHO which results in just displaying the DEL command line.
For example the complete list of backup files is:
Y:\masters\Level2\Level3\Level4\Level5\Test1.bak
Y:\Folder2\masters\Level3\Test2.bak
Y:\Folder3\Level2\masters\Level4\Test3.bak
Y:\Folder4\Level2\Level3\Level4\Level5\Test4.bak
Y:\Folder5\Level2\Test5.bak
Y:\Folder6\Level2\Level3\Level4\Level5\Level6\Test6.bak
Y:\Folder7\masters\Test7.bak
The files deleted would be:
Y:\masters\Level2\Level3\Level4\Level5\Test1.bak
Y:\Folder2\masters\Level3\Test2.bak
Y:\Folder3\Level2\masters\Level4\Test3.bak
Y:\Folder7\masters\Test7.bak
And the files remaining would be:
Y:\Folder4\Level2\Level3\Level4\Level5\Test4.bak
Y:\Folder5\Level2\Test5.bak
Y:\Folder6\Level2\Level3\Level4\Level5\Level6\Test6.bak
Then use in your batch file:
forfiles /P "Y:\" /S /D -1096 /M *.bak /C "C:\Temp\DeleteBackup.bat #PATH"
It is of course possible to modify DeleteBackup.bat to check if directory in second directory hierarchy level is masters.
#echo off
for /F "tokens=3 delims=\" %%I in ("%~1") do if /I "%%I" == "masters" ECHO del "%~1"
This code would delete from the complete list above the files:
Y:\Folder2\masters\Level3\Test2.bak
Y:\Folder7\masters\Test7.bak
And the files remaining would be:
Y:\masters\Level2\Level3\Level4\Level5\Test1.bak
Y:\Folder3\Level2\masters\Level4\Test3.bak
Y:\Folder4\Level2\Level3\Level4\Level5\Test4.bak
Y:\Folder5\Level2\Test5.bak
Y:\Folder6\Level2\Level3\Level4\Level5\Level6\Test6.bak
Robert Chizmadia Jr. asked in an already deleted comment:
Is it possible to use GOTO instead of calling another batch file on FORFILES command line?
The answer on this additional question:
FORFILES is not an internal command of cmd.exe like FOR. It is a console application stored in directory %SystemRoot%\System32 if used version of Windows has it pre-installed at all.
The command to execute as specified after FORFILES option /C must be an executable or script. That is the reason why cmd /C is always used when an internal command of Windows command interpreter cmd.exe like DEL should be executed by FORFILES whereby the really complete command would be %SystemRoot%\System32\cmd.exe /C.
So it is not possible to use a command like GOTO in FORFILES command as there is no executable or script with name GOTO.
Also GOTO in a FOR loop exits the loop and therefore interpreting of command lines of batch files continues on another position in batch file.
However, it is possible to use the same batch file for the file path evaluation and backup file deletion as used to run FORFILES command.
Example 1 with batch file not expecting any parameter for default operation:
#echo off
if not "%~1" == "" (
for /F "tokens=3 delims=\" %%I in ("%~1") do if /I "%%I" == "masters" ECHO del "%~1"
goto :EOF
)
%SystemRoot%\System32\forfiles.exe /P "Y:\" /S /D -1096 /M *.bak /C "%~f0 #PATH"
If this batch file is executed with an argument, it runs the FOR loop written to check if second directory in file path is masters and delete this file in this case after removing ECHO. Otherwise on starting the batch file without any parameter the batch file runs the FORFILES executable.
Example 2 with batch file expecting 1 or more parameters for default operation:
#echo off
if "%~1" == "#Delete:Backup#" (
for /F "tokens=3 delims=\" %%I in ("%~2") do if /I "%%I" == "masters" ECHO del "%~2"
goto :EOF
)
rem Other commands processing the parameters.
%SystemRoot%\System32\forfiles.exe /P "Y:\" /S /D -1096 /M *.bak /C "%~f0 #Delete:Backup# #PATH"
rem More commands executed after the deletion of the backup files.
This is nearly the same as example 1 with the difference that if first parameter used on running the batch file is case-sensitive the string #Delete:Backup#, the batch file expects as second parameter the name of a backup file with full path being deleted if second directory in file path is masters.
Like in all batch code examples the command ECHO must be removed before del command also in this code example to really execute the deletion of the backup files.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
for /?
forfiles /?
goto /?
if /?
set /?

CMD batch file for user profile migration

I am working on a refresh project, and I am rebuilding and swapping out a lot of computers. When doing a reimage, I have a script I can run which will copy the Desktop, Favorites, and Documents from all user profiles to a network share.
What I don't have yet, is a script for hardware replacements (vs a reimage) that will transfer data directly from the old computer to the new one. As with my other script, I need it to transfer data from the Desktop, Favorites, and Documents folders for all user directories present on the old machine. If I wanted to go a step further, I might exclude specific user profiles such as Public, Default, my own profile, etc, but a more basic script would still work.
I have done some batch scripting on my own, but I'm not sure what the syntax needs to be to have it cycle through all the user profiles on a remote machine.
Here is what I have tried so far:
#echo off
Set /p remotepc=Enter remote hostname:
for /D %%D in ("\\%remotepc%\USERS\*") do (xcopy \\%remotepc%\Users\%%~fD\Desktop "C:\Users\%%~nxD\Desktop" /H /E /Y /K /I /R /C)
for /D %%D in ("\\%remotepc%\USERS\*") do (xcopy \\%remotepc%\Users\%%~fD\Documents "C:\Users\%%~nxD\Documents" /H /E /Y /K /I /R /C)
for /D %%D in ("\\%remotepc%\USERS\*") do (xcopy \\%remotepc%\Users\%%~fD\Favorites "C:\Users\%computername%\%%~nxD\Favorites" /H /E /Y /K /I /R /C)
pause

Deleting all files and directories from desktop except .lnk

Im trying to write a script for keep clear my desktop. I want to delete all files and directories except the shortcuts.I use Windows 10. My batch code is the following:
#echo off
COLOR 0E
cd "C:/Users/DA/Desktop"
FORFILES /S /C "if #ext!=lnk del /F /Q /S"
rd /S /Q "."
pause
exit
Maybe it is a dumb error, but Im a newbie in Windows command line. Thanks in advance.
There are several issues in your code:
You must precede the command line after the /C switch of forfiles with cmd /C, because you are using internal console commands (if, del). If you omit cmd /C, forfiles tries to find a program file named if, which does not exist.
There is no comparison operator != for the if statement. You mean not equal, so you need to state if not <expression1>==<expression2> instead.
The #ext variable expands to the file extension enclosed in quotation marks, so you need to state them around lnk also. Since the "" are in the quoted command line behind forfiles /C, you need to escape them like \" in order to establish literal " characters.
You forgot to specify what to delete at the del command.
The switches /S of forfiles and also del mean to process also items in sub-directories, but I assume you do not want that, because you want to clean up your Desktop directory.
There is the rd command, so I assume you want to remove any directories from the Desktop either. However, rd /S /Q "." tries to remove the entire Desktop directory (which will fail as your batch file changes to that directory by cd). I would put the rd command into the forfiles command line as well, because there is the possibility to check whether or not the currently iterated item is a file or a directory (forfiles features the #isdir variable for that purpose).
The cd command works only if you are running the batch file from the same drive where the Desktop directory is located (unless you provide the /D switch). I would go for the pushd command, which changes to the Desktop directory temporarily, until a popd command is there.
Instead of hard-coding the location of the Desktop directory, I would use the built-in environment variable %USERPROFILE%, which points to the user profile directory of the currently logged on user, where the Desktop directory is located in.
The exit command without the /B switch does not only end the batch file, it also terminates the command interpreter instance the batch file is running in. This does not matter when you run the batch file by double-clicking, but it does matter when you execute it within command prompt.
Here is the corrected and improved code:
#echo off
title Clean Up Desktop & rem // (this is the window title, just for fun)
color 0E
pushd "%USERPROFILE%\Desktop" || exit /B 1 & rem // (the command after `||` runs if `pushd` fails, when the dir. is not found)
rem /* Here you can see how to distinguish between files and directories;
rem files are deleted with `del`, directories are removed with `rd`.
rem The upper-case `ECHO`s are there for testing purposes only;
rem remove them as soon as you actually want to delete any items: */
forfiles /C "cmd /C if #isdir==FALSE (if /I not #ext==\"lnk\" ECHO del /F /Q #relpath) else ECHO rd /S /Q #relpath"
pause
popd & rem // (this restores the previous working directory)
exit /B & rem // (this quits the batch file only; not necessary at the end of the script)
You can try something like that :
#echo off
COLOR 0E
CD /D "%userprofile%\Desktop"
Rem To delete folders
for /f "delims=" %%a in ('Dir /b /AD ^| find /v "lnk"') do echo rd /S /Q "%%a"
pause
Rem To Delete files
for /f "delims=" %%a in ('Dir /b ^| find /v "lnk"') do echo del /F /Q /S "%%a"
pause
exit
NB: When your execution is OK, just get rid of echo command
You can use the for and if commands to accomplish this:
#echo off
COLOR 0E
cd C:/Users/DA/Desktop
for /d %x in (*) do #rd /s /q "%x"
for %i in (*) do if not %i == *.lnk del "%i"
pause
Pretty simple and works great.
Make sure that %i and %x are in "".

Scheduled Task .bat - check if network drive ready

I have a scheduled task in Windows Server 2003 R2 that is supposed get some files from a network location (mapped drive) and copy them to a local folder in preparation for an FTP sync to a mobile device later that day.
The task runs no problem when I click it and run it. Task scheduler says it is running updates the time it has run and the files appear in the correct location. Yet...
When the task is supposed to run over night (and I am not already logged in) the task runs (task scheduler indicates that the task ran at the specified time) but the file copy does not occur. I suspect this has to do with the task logging the account in, then running the file copy before the Network Drive has been connected and is ready.
Here is my code from the batch file:
#echo off
FORFILES /p "K:\Oncology\BSWRICS-MDM" /s /m *.* /c "cmd /c Del #path" /d -30
set "cleanup=K:\Oncology\BSWRICS-MDM"
for /f "usebackq tokens=*" %%a in (`dir /b/s/ad "%cleanup%" ^| sort /r`) do (rmdir "%%~a" 2>nul && echo:Removed: "%%a")
xcopy K:\Oncology\BSWRICS-MDM\*.* C:\wamp\www\Portal\files\BSWRICS-MDM /Y /S
FORFILES /p "C:\wamp\www\Portal\files\BSWRICS-MDM" /s /m *.* /c "cmd /c Del #path" /d -30
The first few lines delete files older than 30 days from the local folder, then the xcopy occurs. As I said, this script works perfectly when I log in first.
Is there some code I can insert at the start to have the script check if the network drive is ready and only if TRUE, proceed to the next instruction?
Some answers to expected questions:
- The network drive letter never changes.
- The account that logs in with the scheduled task is the same one I can successfully run the task from.
- The task actually runs (logged in task scheduler) but there is no evidence of the file copy having been performed.
Thanks in advance.
You could delete the mapped drive and try to map it again, and then wait until the errorlevel shows it is connected before proceeding.
#echo off
:LOOP
net use Y: /delete
net use Y: \\server\share
if errorlevel 1 (
goto :ERROR
) else (
goto :OK
)
:ERROR
echo ERROR!
rem Try again!
timeout /t 5
goto :LOOP
:OK
echo OK!
rem Carry on!
pause >nul

Resources