I've been using the following batch file to backup a certain directory on a Windows Server machine for a long time. The batch file is run by a Windows Scheduled Task every day at a certain time and it zips a specific folder to a backup location after deleting the oldest .7z file (7z = www.7-zip.org).
This way I only ever have the number of .7z files specified in BackupNr in my backup folder and I don't have to manually delete the oldest .7z file.
The problem is the "Set BackupNr=1" line. Using BackupNr=1 I always have TWO .7z archives in my backup folder after the batch file has run.
I can't figure out what I need to change so that only ONE archive is kept whenever the batch file runs. How can I fix this?
#echo off
:: The name of the backup file that will be created. It will use the current date as the file name.
#For /F "tokens=1,2,3,4 delims=/ " %%A in ('Date /t') do #(
Set FileName=%%A%%B%%C%%D
)
:: The name of the folders where all the backup .zip and report files will be stored.
Set ArchiveFolder=D:\Backup\Manual\Archives
Set ReportFolder=D:\Backup\Manual\Reports
:: The name of the folder that will be backed up, i.e. the AppData folder.
Set FolderToBackup=C:\AppData
:: The number of .zip files and .txt reports to keep. Older archives will be deleted according to their age. This ensures we only keep the most recent X number of backups.
Set BackupNr=1
:: Delete oldest backup archives so we only keep the number of archives specified in "skip=".
echo.>> DeletedBackups.txt
date /t >> DeletedBackups.txt
echo.>> DeletedBackups.txt
echo These older backups were deleted:>> DeletedBackups.txt
for /F "skip=%BackupNr% delims=" %%a in ('dir /b /o-d %ArchiveFolder%\*') do (
echo %ArchiveFolder%\%%a%1>> DeletedBackups.txt
del /f /q %ArchiveFolder%\%%a%1
)
echo.>> DeletedBackups.txt
echo These older reports were deleted:>> DeletedBackups.txt
for /F "skip=%BackupNr% delims=" %%a in ('dir /b /o-d %ReportFolder%\*') do (
echo %ReportFolder%\%%a%1>> DeletedBackups.txt
del /f /q %ReportFolder%\%%a%1
)
echo Starting the backup: %DATE% %TIME% >> %ReportFolder%\%FileName%.txt
:: Adds all files to 7z archive using BCJ2 converter, LZMA with 8 MB dictionary for main output stream (s0), and LZMA with 512 KB dictionary for s1 and s2 output streams of BCJ2.
C:\PROGRA~1\7-Zip\7z.exe a -t7z %ArchiveFolder%\%FileName%.7z %FolderToBackup%\* -m0=BCJ2 -m1=LZMA:d23 -m2=LZMA:d19 -m3=LZMA:d19 -mb0:1 -mb0s1:2 -mb0s2:3 >> %ReportFolder%\%FileName%.txt
echo Backup finished at: %DATE% %TIME% >> %ReportFolder%\%FileName%.txt
:: Write the backup Start and End times to the BackupInfo.csv file.
gawk -f BackupRecord.awk %ReportFolder%\%FileName%.txt >> %ReportFolder%\BackupReport.csv
:: Write the file size of the backup .zip file that was just created to the log file.
set size=0
call :filesize %ArchiveFolder%\%FileName%.7z
echo Backup archive file size: %size% bytes >> %ReportFolder%\%FileName%.txt
exit
:: set filesize of 1st argument in %size% variable, and return
:filesize
set size=%~z1
exit /b 0
Thanks.
The /b switch in the dir command uses no header nor summary. result is a plain list of archives, in this case orderer descending by creation time, the most recent first.
The problem is the skip=%BackupNr% in
for /F "skip=%BackupNr% delims=" %%a in ('dir /b /o-d %ReportFolder%\*') do (
echo %ReportFolder%\%%a%1>> DeletedBackups.txt
del /f /q %ReportFolder%\%%a%1
)
as skip the first line, so the delete command erases all archives EXCEPT the most recent.
then you execute the backup, so a new file is added to the directory. Result, two files.
If you want only the last one, you should first perform the backup and after the deletion, or remove the skip=%BackupNr% from the for command.
Related
I am trying to create a batch script to take a directory within Windows, and compress it with 7-zip using a batch script, but limit the maximum file size of each compression part to max 4GB each, limiting the total amount of revision compression sets to 7 (for a weekly backup, Monday to Sunday). The oldest will be removed on the next backup job.
I tried playing with the REM CHECK FOR REVISIONS code, but am not knowledgeable enough to understand how to proceed with this.
#ECHO OFF
REM Script created for AVIMark Backup
REM Install 7-zip and make sure to create an environment variable to allow for shortcuts
REM https://www.7-zip.org/download.html
REM set PATH=%PATH%;C:\Program Files\7-Zip\
REM echo %PATH%
REM 7z
REM 7ZIP ENVIRONMENT VARIABLE PATH
set PATH=%PATH%;C:\Program Files\7-Zip\
7z
cls
REM SET SOURCE, DESTINATION AND REVISION AMOUNT VARIABLES
SET source="C:\AVImark"
SET destination="C:\AVImarkBackup"
SET revisions=7
REM Change Directory to the source data folder
cd "%source%"
REM Run the command to compress the directory, gather the date stamp and insert compressed file into destination folder
7z a -r -v4g "%destination%\%DATE:~7,2%.%DATE:~4,2%.%DATE:~-4% Backup".7z
REM CHECK FOR REVISIONS
cd "%destination%"
for /f "skip=%revisions% eol=: delims=" %%F in ('dir /b /o-d /a-d *.7z') do #del "%%F"
EXPECTED RESULTS
I'd like to have every backup set (in its date format) to be limited to 7 revisions in total.
ie: https://imgur.com/a/Q50n0bD
ACTUAL RESULTS
There is no revision check and cleanup happening on the oldest job, it keeps adding more sets.
#echo off
setlocal
rem Script created for AVIMark Backup
rem Install 7-zip and make sure to create an environment variable to allow for shortcuts
rem https://www.7-zip.org/download.html
rem set PATH=%PATH%;C:\Program Files\7-Zip\
rem echo %PATH%
rem 7z
rem 7ZIP ENVIRONMENT VARIABLE PATH
set "PATH=%PATH%;C:\Program Files\7-Zip"
rem SET SOURCE, DESTINATION AND REVISION AMOUNT VARIABLES
set "source=C:\AVImark"
set "destination=C:\AVImarkBackup"
set "revisions=7"
set "datestamp=%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%"
rem Change Directory to the source data folder
pushd "%source%" && (
rem Run the command to compress the directory, gather the date stamp and insert compressed file into destination folder
7z a -r -v4g "%destination%\%datestamp% Backup.7z"
popd
)
rem CHECK FOR REVISIONS
pushd "%destination%" && (
rem Option 1
rem Delete by last modified filedate
forfiles /d -7 /m "*Backup.7z.*" /c "cmd /c echo del #path"
rem Or use:
rem Option 2
rem Delete by logged date. Requires datestamp yyyy-MM-dd for correct sorting
if exist Backup.log (
findstr /c:"%datestamp%" Backup.log || >> Backup.log echo %datestamp%
) else (
> Backup.log echo %datestamp%
)
for /f "skip=%revisions% delims=" %%A in ('type Backup.log ^| sort /r') do (
echo del "%%~A Backup.7z.*"
)
popd
)
Changed datestamp to yyyy-MM-dd instead of dd.MM.yyyy.
The former datestamp is better for sorting.
If you want a datestamp independant of locale, search for
wmic os get localdatetime commands on this site.
Use of pushd and popd instead of cd.
The use of && is to run following command if the last command was successful.
|| is to run following command if the last command failed.
2 options are offered for use to delete the revisions:
The 1st is the use of forfiles.
Currently as set, it will delete revisions older
than 7 days from the current date.
This might be suitable, unless no backups have been
done for 7 days which may result in no backups.
The 2nd is the use of Backup.log.
The date is appended to the log file and then the
for loop reads the log file with type, and sort
reverses the sort to make the oldest 1st and latest
last. The skip avoids the processing of the 1st
7 revisions. The rest will be used to delete the
archives by the file pattern.
Remove the code of the option not wanted.
del commands are echoed for testing. If satisfied,
remove the echoes to make the deletion actually work.
I have multiple folders with multiple files with the same name and then a timestamp. Example:
foo_2017.01.16.png
foo_2017.01.15.png
foo_2017.01.14.png
bar_2017.01.16.png
bar_2017.01.15.png
bar_2017.01.14.png
file_2017.01.16.png
file_2017.01.15.png
file_2017.01.14.png
What I'm needing to do is create a batch file that will parse out only the name before the _timestamp and keep the last 10 of each file name. I'm not very well versed in batch and could really use some help here. The Date Modified for every file is the same, so I cannot just say keep only the last 10 days, otherwise I could handle that.
EDIT:
I have a batch file that deletes files in a specific folder older than 28 days that looks like the following, I just do not know how to modify it to iterate through for each file name specifically and to not go by Date Modified:
/c echo #FILE
forfiles -p "C:\workspace\SeleniumTestResults" -s -m *.* /D -28 /C "cmd /c del #path"
Again, this batch is definitely not my area
#echo off
setlocal
REM create some files for testing:
break>foo_2017.01.16.png
break>foo_2017.01.15.png
break>foo_2017.01.14.png
break>bar_2017.01.16.png
break>bar_2017.01.15.png
break>bar_2017.01.14.png
break>file_2017.01.16.png
break>file_2017.01.15.png
break>file_2017.01.14.png
dir *.png
set keep=2
for /f "delims=_" %%a in ('dir /b *.png') do (
for /f "skip=%keep% delims=" %%b in ('dir /b /o-n "%%~a*.png"') do del "%%b"
)
dir *.png
Here's what I have;
On a windows-based web server there are roughly 1,000 zip files, each with dozens of log files inside. I already have a script that goes through each archive and deletes all but one specific file type (in an attempt to save diskspace and delete things I don't need). Then, the script unzips each archive to their own folder. And I know how to code the reverse of that to zip them back when I'm done.
Here's what I need to figure out;
Once I run the previously mentioned script (we call it garbageman because it cleans out the garbage in the zip files) I need to go through the remaining 5 or 6 files in each of the newly created unzipped folders, and look for a specific string in each file. If I find the string, I delete everything that is not that string, and save it to a file called "export.txt" in that folder. Then, I move to the next unzipped file, and so on. Once completed, I need re-zip everything back together into their own archives
Here's what I have for code so far. Any help is extremely appreciated.
cd "C:\Program Files\7-Zip"
FOR %%c in (C:\Users\xxxxxx\Desktop\LogQueue\*.*) DO 7z d %%c "-x!xstore*" -r
FOR /R "C:\Users\xxxxxx\Desktop\LogQueue" %%I in ("*.zip") do (
"%ProgramFiles%\7-Zip\7z.exe" x -y -o"%%~dpnI" "%%~fI"
)
cd "C:\Users\xxxxxxx\Desktop\LogQueue"
FOR /R "C:\Users\xxxxxx\Desktop\LogQueue" %%I in ("*.*") do (
findstr "xxxxxxxx_eReceipt" %%~fI > %%~dpnI\export.txt
pause
)
for /d %%X in (*) do "c:\Program Files\7-Zip\7z.exe" a "%%X.zip" "%%X\"
This is an edit:
This script should do what you want.
Only Change sourcedir and mystring variables.
export.txt will be inside a file called Storage in the root directory of the batch.
:ScriptA
#ECHO ON
MKDIR "%CD%\Storage"
MKDIR "%USERPROFILE%\Desktop\Outx"
GOTO :ScriptB
:ScriptB
::REM ONLY CHANGE
SET "sourcedir=%USERPROFILE%\Desktop\Test"
FOR /R "%sourcedir%\" %%a in (*.txt) do copy "%%a" "%CD%\Storage"
:ScriptC
:ScriptC
#ECHO OFF
SETLOCAL
SET "VARA=%CD%\Storage"
SET "VARB=%USERPROFILE%\Desktop\Out"
::REM ONLY CHANGE
SET "mystring=PUT_STRING_HERE"
FOR %%a IN ("%VARA%\*.txt") DO FINDSTR "%mystring%" "%%a">nul&IF NOT ERRORLEVEL 1 FINDSTR "%mystring%" "%%a">"%VARB%\%%~nxa"
DEL /F "%CD%\Storage\*.txt"
GOTO :ScriptD
:ScriptD
#ECHO ON
COPY /B "%USERPROFILE%\Desktop\Outx\*.txt" "%CD%\Storage\export.txt"
RD /S /Q "%USERPROFILE%\Desktop\Outx"
goto :eof
I have multiple folders that each contain a config folder. In the config folder there is a .cfg file and a backup folder. I would like to copy the .cfg file to the backup folder with a date extension.
Here is my folder structure:
\Folder1\config
folder1.cfg
\backup
\Folder2\config
folder2.cfg
\backup
\Folder3\config
folder3.cfg
\backup
Each of the above folders has a config folder. In each config folder there is a .cfg file and a backup folder. How can I step through each Folder*\config directory and copy the folder*.cfg file to the backup folder and rename it to folder3.cfg.yyyymmdd? I actually have about 40 folders that I would need to this for on a Windows server. Any help would be greatly appreciated.
REM
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
for /f "delims=." %%a in ('wmic OS Get localdatetime ^| find "."') do set "wmicdt=%%a"
SET "wmicdt=%wmicdt:~0,8%"
FOR /f "delims=" %%a IN ('dir /b /ad "%sourcedir%" ' ) DO (
IF EXIST "%sourcedir%\%%a\config\%%a.cfg" (
MD "%sourcedir%\%%a\config\backup" 2>NUL
COPY /b "%sourcedir%\%%a\config\%%a.cfg" "%sourcedir%\%%a\config\backup\%%a.cfg.%wmicdt%" >nul
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit.
The SET "wmicdt=%wmicdt:~0,8%" line selects the first 8 characters of the date/time string in wmicdt, which is yyyymmdd. If you want the time as well, simply omit this line.
Here is your answer.
#echo off
:loop
for /l %%g in (1,1,3) do (
copy "Folders\Folder%%g\config\Folder%%g.cfg" "Folders\Folder%%%g\config\Backup\"
rename "Folders\Folder%%g\config\Backup\Folder%%g.cfg" "Folder %date%.cfg"
timeout>nul 1
)
:end
cls
echo.
echo ========
echo = Done =
echo ========
echo.
pause>nul
I was trying to make a file with modification date as name but i had some problems with time (22-03-2012 12:22).
This 12 ==>:<== 22 is trouble me. I don't know how to get rid of this. So instead you have current date as a file name.
Sorry for my English.
Here is file with that batch and folders, so you can see how it works
i looking for an solution using a Batchfile to do the following.
I do every day a backup of my databases in an folder, which named after the day eg.
2013-05-13
. This is already fine.
Now the Problem:
At the end of a month i want to combine the oldest 10 folders (including all files) to an archive folder.
All files from the 10 oldest folders should moved to the archive folder. Same files should overwritten (oldest to new) and the folder (now empty) should also removed.
Best Regards
This should move the contents of the oldest 10 folders to an archive folder (which should pre-exist), overwriting and keep the latest copies, and remove the folders: but it doesn't expect subdirectories in the backup folders.
After you test it you can schedule the batch file.
#echo off
setlocal enabledelayedexpansion
cd /d "d:\source\folder"
set "c=0"
for /f "delims=" %%a in ('dir /ad /b /od') do (
set /a c=c+1
if !c! LEQ 10 (
echo "%%a"
move /y "%%a\*.*" "D:\destination\archive\" >nul
rd "%%a"
)
)
pause
The easiest way would be to install UnixUtils to get mv, tail and head utilities
Then
dir /b /AD /OD|tail -n 10 > temp.txt
gives you list of 10 newest directories in current one
for /f "delims=" %%i in (temp.txt) do echo D|mv -f "c:\source\%%i" "c:\destination\%%i" /y >temp.bat
creates script moving them somewhere
call temp.bat
calls it.