I am writing an automated backup program that can be scheduled with Task Scheduler.
I've got it done to the point where it will successfully make sure that it can read/write both the source and destination folders, then copy everything from the source to the destination, ignoring files that haven't been changed. What I want to do is "sync" the destination folder to the source folder. I've tried making it echo the filenames from %destdir% (variable for the inputted destination path) into a .txt file, then compare the .txt file to the filenames in %sourcedir% (variable for the inputted source path), deleting anything that isn't listed in the .txt file. This works on paper, but I think my syntax may be wrong, as I'm not entirely familiar with if and for. This is what the backup routine looks like so far:
echo Copying files...
xcopy /s/e /y /h /k /z /d /i %sourcedir% %destdir%
for /r "%destdir%" %%F in (*.*) do echo %%F>> list.txt
for /F "tokens=2* delims=\" %%I in (list.txt) do if not exist "%sourcedir%" del "%destdir%"
del list.txt
pause
if %errorlevel%==0 goto success
if %errorlevel%==gtr 0 goto failure
I must be doing something wrong here (my guess is for /F "tokens=2* delims=\" %%I in (list.txt) do if not exist "%sourcedir%" del "%destdir%". Something about that doesn't seem right, but I can't quite put my finger on it. I've been debugging for a good hour or so now, and I can't seem to fix this problem.
Any help would be appreciated.
ECHO Copying files...
SET "SOURCEDIR=Dir to copy"
SET "DESTDIR=Dir where the files shoud be"
XCOPY /s/e /y /h /k /z /d /i "%SOURCEDIR%" "%DESTDIR%"
FOR /R "%DESTDIR%" %%F IN (*.*) DO ( ECHO %%F>> list.txt
FOR /F "tokens=2* delims=\" %%I in (list.txt) DO IF NOT EXIST "%SOURCEDIR%" DEL "%DESTDIR%"
DEL list.txt
IF "%errorlevel%" EQU "0" ( goto :SUCCESS )
IF "%errorlevel%" GTR "0" ( goto :FAILURE )
:SUCCESS
<<command you want to use here.>>
GOTO :END
:FAILURE
<<command you want to use here.>>
GOTO :END
:END
EXIT /B "%ERRORLEVE%"
Related
Here I am trying to execute a batch script which deletes subfolders under folder "updates" in all remote machines. List of servers are passed as input
(serverlist.txt)
echo off
for /f %%l in (C:\deleteauto\delrem\serverlist.txt) do
if exist C:\updates goto sub
if not exist C:\updates goto nofile
:sub
del /f /q "C:\updates\*.*"
for /d %%d in ("C:\updates\*.*") do rmdir /s /q "%%d"
echo folder is deleted in %%l >>c:\finaloutput.txt
:nofile
echo No folders in %%l >>c:\final output.txt
Can someone please help in rectifying the errors. Script executed but outputs nothing.
Try this code:
#echo off
for /f "tokens=*" %%l in (C:\deleteauto\delrem\serverlist.txt) do (
if exist "\\%%l\C$\updates" (
pushd "\\%%l\C$\updates"
del /f /q "*."
for /d %%d in ("*.") do rmdir /s /q "%%d"
echo Folder is deleted on server: %%l>>finaloutput.txt
popd
) else (
echo Folder does not exist on server: %%l>>finaloutput.txt
)
)
Here's an example of how I may tackle the task:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "SvrLst=C:\deleteauto\delrem\serverlist.txt"
If Not Exist "%SvrLst%" GoTo :EOF
(For /F UseBackQ^ Delims^=^ EOL^= %%G In ("%SvrLst%"
) Do PushD "%%~G\C$\updates" 2>NUL && (
RD /S /Q . 2>NUL
Echo Instruction to empty directory applied on %%~G & PopD
) || Echo Directory path not found on %%~G) 1>"C:\finaloutput.txt"
You will note that I have not stated that the directory was emptied. Just because an instruction was applied, does not mean that it was successful at doing so. Unless you check that the \C$\updates directory is completely empty afterwards, you should not imply that it is.
Errors were rectified by #Fire Fox , Thank you! Modified slightly & it worked as expected.
Code:
#echo off
for /f "tokens=*" %%l in (C:\deleteauto\delrem\serverlist.txt) do (
if exist "\\%%l\C$\updates" (
pushd "\\%%l\C$\updates"
del /f /q "\\%%l\C$\updates\*.*"
for /d %%d in ("\\%%l\C$\updates\*.*") do rmdir /s /q "%%d"
echo Folder is deleted on server: %%l>>C:\finaloutput.txt
popd
) else (
echo Folder does not exist on server: %%l>>C:\finaloutput.txt
)
)
My program is almost working but I need some help with the way the content in the .txt files are updating. My program might be messy or sloppy, I am not a good programmer and I have been copying and pasting logic from this website until things started working!!
Program logic step by step
1.Copy all .csv files from folder1 to folder2
2.Delete all existing .txt files in folder2
3.Convert all .csv files in folder2 to .txt files
4.Change data in each .txt file
Before data in txt file
.001
.002
.004
Desired After data in txt file
Input1=.001
Input2=.002
Input3=.004
Actual After data in txt file
.001
.002
.004
Input1=.001
Input2=.002
Input3=.004
I cannot have it append to the bottom of the .txt file I need it to overwrite the existing data.
Any help would be appreciated!!
#echo off
set folder1="Z:\CNC_Dev\EJV\Set Up Info"
set folder_1=Z:\CNC_Dev\EJV\Set Up Info
set folder2="Z:\CNC_Dev\EJV\PW991tetsingbat"
set folder_2=Z:\CNC_Dev\EJV\PW991tetsingbat
set fType=*.csv
set fType2=*.txt
set LineNumber=0
setlocal EnableDelayedExpansion
for /f "delims=" %%f in ('dir /a-d /b /s "%folder_1%\%fType%"') do (
xcopy /e /i /v /h /k /y "%%f" "%folder2%\" 2>nul
)
pause
del /s %folder2%\%fType2%
PAUSE
FOR /R "%folder2%" %%f IN (*.csv) DO REN "%%f" *.txt
PAUSE
#FOR /f "delims=" %%f IN ('dir /b /s "%folder_2%\*.txt"') DO (
set /a "idx+=1"
set "FileName[!idx!]=%%~nxf"
set "FilePath[!idx!]=%%~dpFf"
)
PAUSE
for /L %%i in (1,1,%idx%) do (
echo "!FileName[%%i]!"
pause
set LineNumber=0
del "%TEMP%\!FileName[%%i]!.tmp" 2>nul
for /F "usebackq delims=" %%I in ("%folder_2%\!FileName[%%i]!") do (
set /A LineNumber+=1
echo INPUT!LineNumber!=%%I
) >>"%folder2%\!FileName[%%i]!"
pause
)
echo DONE!
PAUSE
I have a .batch script in my Send to folder on Windows which I use to compress multiple files in the folder to a .zip. The problem I'm having is, it's including the extension in the archive file name.
I've search on google, read a lot of posts on stackexchange etc and none of the solutions posted seem to work for me.
#echo off
for %%A in (*.*) do call :doit "%%A"
goto end
:doit
if "%~x1"==".bat" goto :eof
if "%~x1"==".7z" goto :eof
if "%~x1"==".zip" goto :eof
if "%~x1"==".rar" goto :eof
"C:\Program Files\7-Zip\7z.exe" a -tzip %1.zip %1 -sdel
goto :eof
:end
Myfile.txt -> MyFile.txt.zip
I want to remove the .txt from file name if possible.
You can use %~n1 which uses the filename only of the first argument. Here is a possible solution:
#echo off
for %%A in (*.*) do (call:doit "%%A")
goto end
:doit
if "%~x1" NEQ ".bat" (
if "%~x1" NEQ ".7z" (
if "%~x1" NEQ ".zip" (
if "%~x1" NEQ ".rar" (
"C:\Program Files\7-Zip\7z.exe" a -tzip %~n1.zip %~n1 -sdel
:end
exit /b 0
I'm not sure of the syntax for your compressor program, because the answer you've accepted looks wrong both in the fact spaces aren't protected and %~n1 may be missing it's extension.
You could probably do this as a single line:
#For /F "Delims=" %%A In ('Dir /B/A-D-S-L "%~1"^|FindStr /IVE "\.7z \.bat \.rar \.zip"') Do #"%ProgramFiles%\7-Zip\7z.exe" a -tzip "%%~nA.zip" "%%~A" -sdel
I have a directory with .txt files. I need to loop over them and perform two tasks: pass the file into Oracle's stored proc and move it into archive directory. For some reason second task does not work for me. What am I missing?
REM -----------------------------------------
REM first step changes file extension to .632
REM -----------------------------------------
for /f %%I in ('dir /b \\db01\load\*.txt') do (sqlplus.exe usr/pwd#DB #\\db01\sql\load.sql %%I)
for /f %%I in ('dir /b \\db01\load\*.632') do (move \\file01\archive)
Here's a couple of untested examples:
#Echo Off
PushD "\\db01\load" 2>Nul || Exit /B
For %%A In (*.txt *.632) Do (
If /I "%%~xA"==".txt" sqlplus usr/pwd#DB #"..\sql\load.sql" "%%A"
If /I "%%~xA"==".632" If Exist "..\..\file01\archive\" Move /Y "%%A" "..\..\file01\archive" >Nul
)
PopD
#Echo Off
PushD "\\db01\load" 2>Nul || Exit /B
For %%A In (*.txt) Do sqlplus usr/pwd#DB #"..\sql\load.sql" "%%A"
If Exist "*.632" Move /Y "*.632" "..\..\file01\archive" >Nul
PopD
Additionally, depending upon your sqlplus command requirements, you may wish to look at the Start command usage information, start /?
Basically what's going on is that we are migrating about 50 desktops from XP to 7. I cannot install any extra programs to complete this task. What I am doing is writing a script that copies the Desktop, Favourites, and My Documents, along with a few specific file types from the originating machine to a shared drive for the user. Which later will be able to have all files moved to the new machine they are getting. I'm trying to recursively search through Windows and get all .pst files and other files you will see in the script, and back them up to a folder on the share (but not in a directory structure, I just want all the files in a single directory no matter where they originated from) with the exception of My Documents. Anything they have put in My Documents should be excluded in the search. Anyway, this is what I started with:
#echo off
cls
set USRDIR=
set SHARE=
set /P USRDIR=Enter Local User Directory:
set /p SHARE=Enter Shared Drive Name:
set UPATH="c:\Documents and Settings\%USRDIR%"
set SPATH="g:\!MIGRATION"
set ESRI="%UPATH%\Application Data\ESRI"
net use g: /delete
net use g: \\server\%SHARE%
md %SPATH% %SPATH%\GIS %SPATH%\Outlook %SPATH%\Desktop %SPATH%\Documents %SPATH%\Favorites
if exists %ESRI% md %SPATH%\ESRI
md %SPATH%\misc %SPATH%\misc\GISfiles %SPATH%\misc\XMLfiles %SPATH%\misc\CSVfiles
for /R %%x in (*.mxd) do copy "%%x" "%SPATH%\GIS\"
for /R %%x in (*.dbf) do copy "%%x" "%SPATH%\misc\GISfiles\"
for /R %%x in (*.xml) do copy "%%x" "%SPATH%\misc\XMLfiles\"
for /R %%x in (*.csv) do copy "%%x" "%SPATH%\misc\CSVfiles\"
for /R %%x in (*.pst) do copy "%%x" "%SPATH%\Outlook\"
if exist %ESRI% xcopy /y /d /s /i /z %ESRI% %SPATH%\ESRI && echo ESRI YES || ESRI NO
xcopy /y /d /s /i /z "%UPATH%\Desktop" "%SPATH%\Desktop" && echo DESK YES || DESK NO
xcopy /y /d /s /i /z "%UPATH%\My Documents" "%SPATH%\Documents" && echo DOCS YES || DOCS NO
xcopy /y /d /s /i /z "%UPATH%\Favorites" "%SPATH%\Favorites" && echo FAVS YES || FAVS NO
echo "Script Complete!"
pause
I then decided that I wanted to exclude My Documents just in case so I don't end up with a bunch of duplicates where anything they put in My Documents ends up getting copied twice. So I changed that recursive block to this:
for /R %%x in (*.mxd) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\GIS\"
for /R %%x in (*.dbf) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\misc\GISfiles\"
for /R %%x in (*.xml) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\misc\XMLfiles\"
for /R %%x in (*.csv) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\misc\CSVfiles\"
for /R %%x in (*.pst) do xcopy /y /d /z /exclude:"\My Documents\" "%%x" "%SPATH%\Outlook\"
Anyway, my question is this, is this the most efficient way of doing this? Is there a better way? I'm curious because I have no one here to bounce ideas or anything off of, I'm the sole on site support here. If someone sees a better way or thinks this is how they would do it, please let me know. There are a bunch more filetypes in there, but I removed most of them so the code sample wasn't so long, left enough to get the point across.
EDIT: Just to make it clear, I am not the IT Department for this organization. I'm a technical support liaison for the department to a separate IT division. Our actual IT department calls this a migration, but it's more or less a simple "lets in stall new machines without doing anything to prepare for it" sort of soup sandwich operation. I can't install, remove, or change the systems in any way, I can only backup the files.
Usually, the best option is reduce processing in batch files to the minimum, leaving as much as possible to commands. But if you have to iterate over the file system several times, it is better to do only one pass and process in batch.
Adapted from a more general batch. I have made changes to adjust to what you need, but somethings more specific (your ESRI folder) are not added. Adapt as needed.
#echo off
setlocal enableextensions enabledelayedexpansion
rem Ask for share name
set /P share=Enter Shared drive name:
if "%share%"=="" (
call :error "No share name provided"
goto endProcess
)
rem Configure target of copy
set target=g:
rem Connect to target
net use %target% /delete
net use %target% \\server\%share%
if not exist %target% (
call :error "No connection to server"
goto endProcess
)
rem Configure directory by extension
set extensions=.mxd .dbf .xml .csv .pst
set .mxd=GIS
set .dbf=misc\GISFiles
set .xml=misc\XMLFiles
set .csv=misc\CSVFiles
set .pst=Outlook
rem adjust target of copy to user name
set target=%target%\!MIGRATION\%username%
if not exist "%target%" (
mkdir "%target%"
)
rem Configure source of copy
set source=%userprofile%
if not exist "%source%" (
call :error "User profile directory not found"
goto endProcess
)
rem Resolve My Documents folder
call :getShellFolder Personal
set myDocPath=%shellFolder%
if not exist "%myDocPath%" (
call :error "My Documents directory not found"
goto endProcess
)
rem Ensure target directories exists
mkdir "%target%" > nul 2>nul
for %%e in ( %extensions% ) do mkdir "%target%\!%%e!" >nul 2>nul
rem We are going to filter file list using findstr. Generate temp file
rem with strings, just to ensure final command line is in limits
rem This will contain not desired folders/files or anything that will be
rem copied later
set filterFile="%temp%\filter.temp"
(
echo %myDocPath%
echo \Temporary Internet Files\
echo \Temp\
) > %filterFile%
rem Process user profile, excluding My Documents, IE Temp and not needed extensions
for /F "tokens=*" %%f in ('dir /s /b /a-d "%source%" ^| findstr /v /i /g:%filterFile% ^| findstr /i /e "%extensions%" ') do (
call :processFile "%%~xf" "%%f"
)
rem Now, process "especial" folders
mkdir "%target%\Documents"
xcopy /y /d /s /i /z "%myDocPath%" "%target%\Documents"
call :getShellFolder Desktop
if exist "%shellFolder%" (
mkdir "%target%\Desktop"
xcopy /y /d /s /i /z "%shellFolder%" "%target%\Desktop"
if errorlevel 1 (
call :error "Failed to copy desktop files"
)
)
call :getShellFolder Favorites
if exist "%shellFolder%" (
mkdir "%target%\Favorites"
xcopy /y /d /s /i /z "%shellFolder%" "%target%\Favorites"
if errorlevel 1 (
call :error "Failed to copy favorites"
)
)
rem Finish
goto :endProcess
rem ** subroutines *******************************************
:processFile
rem retrieve parameters
rem : %1 = file extension
rem : %2 = file
set ext=%~1
set file=%~2
rem manage .something files
if "%ext%"=="%file%" (
set file=%ext%
set ext=
)
rem manage no extension files
if "%ext%"=="" (
rem WILL NOT COPY
goto :EOF
)
rem determine target directory based on file extension
set extCmd=%%%ext%%%
for /F "tokens=*" %%d in ('echo %extCmd%^|find /v "%%" ' ) do set folder=%%d
if "%folder%"=="" (
rem file extension not in copy list
goto :EOF
)
copy /y /z "%file%" "%target%\%folder%" >nul 2>nul
if errorlevel 1 (
call :error "Failed to copy [%file%]"
) else (
echo %file%
)
goto :EOF
:getShellFolder
set _sf=%~1
set shellFolder=
if "%_sf%"=="" goto :EOF
for /F "tokens=2,*" %%# in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "%_sf%" ^| find "%_sf%"') do (
set shellFolder=%%$
)
goto :EOF
:error
echo.
echo ERROR : %~1
echo.
goto :EOF
:endProcess
endlocal
exit /b
Try User State Migration Tool from Microsoft - I used it to move around 400 systems in less than 30 days. It takes a bit of setup for the script to run right, but it does a really really good job (and no program to install).
In default mode, it gets all PST files, Document, Desktop, Favorites, and a ton of other folders/registry settings. It also does this for all users on a computer (which can be limited by last login date or number of profiles) as long as the user running it is a local admin.
It may or may not work for what you need, but it's a good choice when designing a migration. It sounds like what you are trying to do can be done with USMT just by removing extra code in the ini files.
This checks and excludes any folder that ends with documents\ (or includes it, so subdirectories too) as IIRC the folder may be called \documents\ or \my documents\ and is case insensitive.
setlocal enabledelayedexpansion
for /R %%x in (*.mxd) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\GIS\"
for /R %%x in (*.dbf) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\misc\GISfiles\"
for /R %%x in (*.xml) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\misc\XMLfiles\"
for /R %%x in (*.csv) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\misc\CSVfiles\"
for /R %%x in (*.pst) do set "check=%%~dpx" & if /i "!check!"=="!check:documents\=!" copy "%%x" "%SPATH%\Outlook\"
endlocal