1

I am using adityasatrio's batch file to backup local MySQL dbs and like to be able to only keep the 30 latest backup files. Using root:root for this example.

    @echo off

 set dbUser=root
 set dbPassword=root
 set backupDir="D:\MySQLDumps\dbs\"
 set mysqldump="C:\wamp\bin\mysql\mysql5.6.17\bin\mysqldump.exe"
 set mysqlDataDir="C:\wamp\bin\mysql\mysql5.6.17\data"
 set zip="C:\Program Files\7-Zip\7z.exe"

 :: get date
 for /F "tokens=2-4 delims=/ " %%i in ('date /t') do (
      set yy=%%i
      set mon=%%j
      set dd=%%k
 )

 :: get time
 for /F "tokens=5-8 delims=:. " %%i in ('echo.^| time ^| find "current" ') do (
      set hh=%%i
      set min=%%j
 )

 echo dirName=%yy%%mon%%dd%_%hh%%min%
 set dirName=%yy%%mon%%dd%_%hh%%min%

 :: switch to the "data" folder
 pushd %mysqlDataDir%

 :: iterate over the folder structure in the "data" folder to get the databases
 for /d %%f in (*) do (

 if not exist %backupDir%\%dirName%\ (
      mkdir %backupDir%\%dirName%
 )

 %mysqldump% --host="localhost" --user=%dbUser% --password=%dbPassword% --single-transaction --add-drop-table --databases %%f > %backupDir%\%dirName%\%%f.sql

 %zip% a -tgzip %backupDir%\%dirName%\%%f.sql.gz %backupDir%\%dirName%\%%f.sql

 del %backupDir%\%dirName%\%%f.sql

 )
 popd

Now I have had a good look at the following questions:

Batch file to delete files older than N days

https://serverfault.com/questions/49614/delete-files-older-than-x-days

Batch file that keeps the 7 latest files in a folder

Windows batch file only keeping the last 30 files

and am now wondering if I can simply add (https://stackoverflow.com/a/14267137/1010918)

for /f "skip=30 delims=" %%A in ('dir /a:-d /b /o:-d /t:c *.sql ^2^>nul') do if exist "%%~fA" echo "%%~fA"

(yes I will later change echo to del but first I like to see what will happen)

or (https://stackoverflow.com/a/13368077)

for /f "skip=30 eol=: delims=" %%F in ('dir /b /o-d *.sql') do @del "%%F"

at the end of the batch file, right under

 del %backupDir%\%dirName%\%%f.sql

to make this happen?

I have never done this before but have searched for automated local backup apps/php scripts/mysqldump commands/etc for MySQL dbs, even had a go with Workbench only to discover that no scheduling can be set in the community edition (thank you Oracle).

All the other apps either need to have someone open the app and hit "run now" or want you to pay for setting up a schedule (no thanks).

I think this can be done with the tools at hand on a Windows 7 and later versions machine. Please help me add this functionality to the script, that would be great, thank you.

edit1:

When adding the quote commands nothing happens. Also the created backup directory only displays the time but not the year, month and day. Doing further research to find out why. Any ideas?

This comment delete all but X most recent folders talks about deleting the 5 latest folders, though when I use it like this

for /f "skip=2 delims=" %%a in ('dir %backupDir%\%dirName% /o-d /b') do rd /S /Q "%backupDir%\%dirName%\%%a"

the error is the following.

The system cannot find the file specified.
The system cannot find the path specified.

edit2: Below is the code that with @foxidrive help sets the folder name as I like to have it, but the last bit, trying to only keep the 3 latest folders (for testing purposes only 3) and delete the rest of the folders in the backupDir does not seem to work out.

Thank you for any help.

     @echo off

 set dbUser=root
 set dbPassword=root
 set "backupDir=D:\MySQLDumps\dbs\"
 set "mysqldump=C:\wamp\bin\mysql\mysql5.6.17\bin\mysqldump.exe"
 set "mysqlDataDir=C:\wamp\bin\mysql\mysql5.6.17\data"
 set "zip=C:\Program Files\7-Zip\7z.exe"

rem The four lines below will give you reliable YY DD MM YYYY HH Min Sec MS variables in XP Pro and higher.

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"

 set "dirname=%YY%-%MM%-%DD% %HH%-%Min%-%Sec%"

 echo "dirName"="%dirName%"
 pause

 :: switch to the "data" folder
 pushd "%mysqlDataDir%"

 :: create backup folder if it doesn't exist
 if not exist "%backupDir%\%dirName%\" mkdir "%backupDir%\%dirName%"

 :: iterate over the folder structure in the "data" folder to get the databases




 for /d %%f in (*) do (
 echo processing folder "%%f"

 "%mysqldump%" --host="localhost" --user=%dbUser% --password=%dbPassword% --single-transaction --add-drop-table --databases %%f > "%backupDir%\%dirName%\%%~nxf.sql"

 "%zip%" a -tgzip "%backupDir%\%dirName%\%%~nxf.sql.gz" "%backupDir%\%dirName%\%%~nxf.sql"

  del "%backupDir%\%dirName%\%%~nxf.sql"

 )
 popd

 :: delete all but the latest 3 folders

 for /f "skip=3 delims=" %%A in ('dir /b /ad /o-n "%backupDir%\%dirName%\*"')  do @echo rd /s /q "%backupDir%\%dirName%\%%~A"

pause
Community
  • 1
  • 1
lowtechsun
  • 1,644
  • 3
  • 22
  • 49
  • And what happens now when you use the quoted commands? – wOxxOm Aug 03 '15 at 12:38
  • @wOxxOm Realized I did not have 7zip but WinRAR, just installing 7zip. Is this also doable with already installed WinRAR? I guess so, but for ease happy to use 7zip as well since it is Open Source. – lowtechsun Aug 03 '15 at 12:40
  • @wOxxOm the problem is that I am not sure exactly what I am doing and that I would like to add the functionality of keeping only the latest 30, or for test cases 3 MySQL backed up .sql files in the backup directory. From what I understand the dbs are being zipped with 7zip, right? So I don't should not have .sql files in the backup dir but .7z files, right? Something does happen but I cannot see any .sql or .7z files in the backup dir. How can I stop the cmd window from closing once the batch file has run please? There is info in the cmd window, perhaps that will help me understand better. Thx – lowtechsun Aug 03 '15 at 12:54
  • @wOxxOm OK with pause and @echo off I can see the commands and it stops at the end! Thx! The script though created a folder with only the current time like so `_1500` instead of with the current year month day and time. Why please? Have not yet added the quoted commands. Doing this now and setting `skip=2`. And yes with the quoted command the created folders are still there. Somehow I have to tell it to look in the Backup Dir and only keep the 3 latest folders, for this test. When I remove `-` and have `%yy%%mon%%dd%%hh%%min%`only time is set a Backup dir name. Why does that happen? – lowtechsun Aug 03 '15 at 13:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/85009/discussion-between-lowtechsun-and-woxxom). – lowtechsun Aug 03 '15 at 13:42

2 Answers2

2

With the help of @foxidrive above I managed to get the date of the folders as I wanted them to be, them being YYYY-MM-DD HH-MIN-SEC.

In these folders are the the gzipped .sql databses stored thanks to adityasatrio's MySQL Backup Batch Script.

With the help of @Magoo from this answer https://stackoverflow.com/a/17521693/1010918 I managed to get all folders (nameDir) deleted while keeping the latest N folders (nameDir) and also not touching any files that might be in the directory (backupDir).

Here is the complete working script.

Feel free to remove any occurrence of pause and and echo to not see what is going on inside the command prompt.

Additionally add this to Windows Task Scheduler and you have yourself a solid backup solution for a local development environment that makes use of MySQL databases.

Please thank the people that helped me get this done. Without you guys I would have had to use a costly Windows app only to locally save MySQL databases.

(..and for our next trick we are going to email an error log to ourselves if there are errors while backing up the .sql files.. but that is another question and story for another day.. )

 @echo off

 set dbUser=root
 set dbPassword=root
 set "backupDir=D:\MySQLDumps"
 set "mysqldump=C:\wamp\bin\mysql\mysql5.6.17\bin\mysqldump.exe"
 set "mysqlDataDir=C:\wamp\bin\mysql\mysql5.6.17\data"
 set "zip=C:\Program Files\7-Zip\7z.exe"

 :: https://stackoverflow.com/a/31789045/1010918 foxidrive's answer helped me get the folder with the date and time I wanted

rem The four lines below will give you reliable YY DD MM YYYY HH Min Sec MS variables in XP Pro and higher.

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"

 set "dirname=%YYYY%-%MM%-%DD% %HH%-%Min%-%Sec%"

 :: remove echo here if you like
 echo "dirName"="%dirName%"

 :: switch to the "data" folder
 pushd "%mysqlDataDir%"

 :: create backup folder if it doesn't exist
 if not exist "%backupDir%\%dirName%\" mkdir "%backupDir%\%dirName%"

 :: iterate over the folder structure in the "data" folder to get the databases

 for /d %%f in (*) do (
 :: remove echo here if you like
 echo processing folder "%%f"

 "%mysqldump%" --host="localhost" --user=%dbUser% --password=%dbPassword% --single-transaction --add-drop-table --databases %%f > "%backupDir%\%dirName%\%%~nxf.sql"

 "%zip%" a -tgzip "%backupDir%\%dirName%\%%~nxf.sql.gz" "%backupDir%\%dirName%\%%~nxf.sql"

  del "%backupDir%\%dirName%\%%~nxf.sql"

 )
 popd

 :: delete all folders but the latest 2


 :: https://stackoverflow.com/a/17521693/1010918 Magoo's answer helped me get what I wanted to do with the folders
 :: for /f "skip=2 delims=" %G in ('dir /B /ad-h /o-d') DO echo going to delete %G

 :: below following my version with rd (remove dir) command and /s and /q
 :: remove echo before rd to really delete the folders in question!!
 :: attention they will be deleted with content in them!!

 :: change the value after skip= to what you like, this is the amount of latest folders to keep in your backup directory
    for /f "skip=2 delims=" %%a in (' dir "%backupDir%\" /b /ad-h /o-d') do echo rd /s /q "%backupDir%\%%a"

:: remove pause here if you like and add the file to Windows Task Manager
 pause
Community
  • 1
  • 1
lowtechsun
  • 1,644
  • 3
  • 22
  • 49
1

This is a little more resilient to spaces in folder names, and the date and time routines have been altered
- run it and first check that the "dirName"= folder is in the right format
- and the line at the end should echo the del commands for keeping the lastest 3 backups.

Test the archiving routine and then
remove the echo before the del keyword if it all looks right to you.

 @echo off

 set dbUser=root
 set dbPassword=root
 set "backupDir=D:\MySQLDumps\dbs\"
 set "mysqldump=C:\wamp\bin\mysql\mysql5.6.17\bin\mysqldump.exe"
 set "mysqlDataDir=C:\wamp\bin\mysql\mysql5.6.17\data"
 set "zip=C:\Program Files\7-Zip\7z.exe"

rem The four lines below will give you reliable YY DD MM YYYY HH Min Sec MS variables in XP Pro and higher.

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"

 set "dirname=%YY%%MM%%DD%_%HH%%Min%"

 echo "dirName"="%dirname%"
 pause

 :: switch to the "data" folder
 pushd "%mysqlDataDir%"

 :: create backup folder if it doesn't exist
 if not exist "%backupDir%\%dirName%\" mkdir "%backupDir%\%dirName%"

 :: iterate over the folder structure in the "data" folder to get the databases




 for /d %%f in (*) do (
 echo processing folder "%%f"

 "%mysqldump%" --host="localhost" --user=%dbUser% --password=%dbPassword% --single-transaction --add-drop-table --databases %%f > "%backupDir%\%dirName%\%%~nxf.sql"

 "%zip%" a -tgzip "%backupDir%\%dirName%\%%~nxf.sql.gz" "%backupDir%\%dirName%\%%~nxf.sql"

 del "%backupDir%\%dirName%\%%~nxf.sql"

 )
 popd


 ::keep 3 newest backup *.sql files
for /f "skip=3 delims=" %%a in ('dir "%backupDir%\%dirName%\*.sql" /b /o-d /a-d') do echo del "%backupDir%\%dirName%\%%a"
pause
foxidrive
  • 37,659
  • 8
  • 47
  • 67
  • Thank you. Again the `dirName` only shows e.g. `_1550` but not years-month-day-time. Naturally at the end it says `File Not Found`. FYI I am on Win 7 64 SP1 English version and the long date and long time is shown dddd, d. MMMM yyyy - HH:mm:ss. Is Windows batch file scripting depended on region somehow? Can I provide more info from the system here for you to see better why the error is happening? – lowtechsun Aug 03 '15 at 14:02
  • Changing line 11 to `for /F "tokens=2-4 delims=. " %%i in ("%date%") do (`gets me a folder with `082015_1614`. Though I need the year to come first. – lowtechsun Aug 03 '15 at 14:23
  • wOxxOm told me in chat "i j k variables in that loop expect year, month, day so you should change the order." cmd `date /t` shows day-month-year here. – lowtechsun Aug 03 '15 at 14:37
  • I have added a reliable routine to get the date and time stamp, which works in all locations. The format of the date and time variables change depending on the locale and the machines preferences, so those are unreliable - except if used on a single machine you can rely on not changing in that regard. – foxidrive Aug 03 '15 at 15:09
  • I had `set dirName="%date:~6,4%-%date:~3,2%-%date:~0,2% %hh%:%min%" echo "dirName"="%dirname%" pause mkdir %dirname%` but then it could not find the specified folder due to a space in the `dirName`. Trying your edit now. – lowtechsun Aug 03 '15 at 15:15
  • The quotes used in the set commands now have different positions such as you see here `set "var=data"` which allows the use of joined variables with surrounding quotes - so that long filename elements like spaces can be handled in a reliable way. You will see this sort of thing above, for example `"%backupDir%\%dirName%\"` with the surrounding quotes. – foxidrive Aug 03 '15 at 15:19
  • Does it work as I posted the code without changing it? if it does then you can modify the date string. `:` is an illegal character in a filename. Try other characters. – foxidrive Aug 03 '15 at 15:30
  • I changed it to `set "dirname=%YYYY%-%MM%-%DD% : %HH%-%Min%-%Sec%` and that messes it up saying the dirName is invalid. Then without `-`, `:` or spaces or anything in the dirName adding `Sec` so `set "dirname=%YY%%MM%%DD%%HH%%Min%%Sec%"` running it 5+ times folders are left there and `echo` tells me `File Not Found`. Even though date is coming closer to needed format, even without delimiters, it does not seem to find the dirName to delete. Ok to use space and `-` instead? Tried and nada. As u posted `echo` = `File Not Found`. Getting closer though. – lowtechsun Aug 03 '15 at 15:44
  • Check if the .sql files are being created in `"%backupDir%\%dirName%"` and look for error messages on the screen. Put a `pause` command after the first `del` command to check for them. – foxidrive Aug 03 '15 at 21:57
  • The .sql files are created in the folder nameDir perfectly with the dates as I like them. The nameDirs are all in one backupDir as I like them alright. There are no error messages regarding that. The only thing that does NOT happen is that after the creation of the nameDir folders all but the N latest FOLDERS are NOT being deleted. All the nameDir folders keep staying there. `echo` confirms this with message. See here what I tried and what happens https://stackoverflow.com/questions/31796149/windows-batch-script-to-only-keep-the-n-latest-folders-in-a-directory At it 4 hrs on end. Thx 4 help :) – lowtechsun Aug 04 '15 at 00:00
  • You changed the task from keeping N files to keeping N folders. Tell people when you do that. – foxidrive Aug 04 '15 at 00:28
  • I meant folders (with backup files in them) all the time and if you check my edit history you can see that I changed the title quickly to reflect what I meant. Sorry for the confusion. Did you see what I tried in the other question? Is it a big task to only delete folders, keep n latest with `skip=N` from a directory **but** not touch files in that directory? I think I am pretty close in that other question but unfortunately it also deletes files that are in the backupDir instead of only the created older nameDirs. Have a look if you like. And thank you for your efforts! **MUCH** appreciated! – lowtechsun Aug 04 '15 at 10:27