I am trying to delete all but the newest folder using a batch script.
A similar question has already been asked here, so I tried using that as a template and things are getting screwed up.
The folder that I need to purge of all but the newest folder is actually a folder containing backups. In another script, I am backing up the folder that contains this folder, which also includes the folder that this is a backup.
H:\LOS is the folder being backed up.
H:\LOS\DefaultChromeCopy is the folder that contains backups of H:\LOS\Default that are taken everyday.
I want to backup H:\LOS, but I don't need any of the folders in DefaultChromeCopy since I'm already backing up Default. I will be running this weekly, so I want to temporarily move the newest folder in the DefaultChromeCopy directory to T:\Backups for safe keeping, then delete all the folders in DefaultChromeCopy, and then backup H:\LOS. That backup will also go to T:\Backups, and then I can move the folder that was the newest folder in DefaultChromeCopy back to its original location.
So in the end, I will have a backup of H:\LOS with an empty DefaultChromeCopy folder, and all the folders in H:\LOS\DefaultChromeCopy will have been deleted except for the newest one (which was "moved" temporarily).
So, using the code from the other SO answer as a starting put, I have this (without the asterisks around the echo):
if not exist "T:\Backups" md "T:\Backups"
set "workdir=H:\LOS\DefaultChromeCopy"
set "folder="
for /f "tokens=* delims=" %%i in ('dir %workdir% /AD /B /TW /O-D') do (
set "folder=%%~fi"
**echo** robocopy H:\LOS\DefaultChromeCopy\%folder% T:\Backups\%folder% /e /w:0 /r:2
goto :break
)
:break
echo newest... %folder%
for /f "skip=1 tokens=* delims=" %%i in ('dir %workdir% /AD /B /TW /O-D') do (
echo rd /s /q "%%~fi"
)
I've set up a dummy drive H and dummy drive T and modeled the folders in order to test this out.
You can see that ne is the newest folder.
With the echo denoted by asterisks, I get:
newest... H:\ne
rd /s /q "H:\sdf"
rd /s /q "H:\6"
rd /s /q "H:\5"
rd /s /q "H:\4"
rd /s /q "H:\3"
rd /s /q "H:\2"
rd /s /q "H:\1"
The path for "newest" used to be right but now even that is not right.
I've stopped here, because so much is going wrong already. How can I fix the paths? Also, if I run without the echo, ALL the folders in DefaultChromeCopy (or sometimes, even stranger, all of them except ne and sdf) get copied to T:\Backups, which is not what is supposed to happen. Only the newest folder is supposed to get copied.
Here is the part that will actually do the "backup", and then move %folder% back where it came from (%folder% is the newest folder from DefaultChromeCopy).
robocopy "H:\LOS\" "T:\Backups\LOS_Backup_%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%TIME:~0,2%.%TIME:~3,2%" /e /w:0 /r:2
robocopy T:\Backups\%folder% H:\LOS\DefaultChromeCopy /e /w:0 /r:2
start "" "T:\Backups"
The directories in DefaultChromeCopy are not modified after they are created, so Date Created and Date Modified should be the same. I only want to keep the newest folder in DefaultChromeCopy, by moving it to T:\Backups so I can delete all the folders in DefaultChromeCopy for the backup (I don't need even the newest backup in the big backup I'm taking). Hope this all makes sense...
UPDATE:
Running:
setlocal ENABLEDELAYEDEXPANSION
set "workdir=H:\LOS\DefaultChromeCopy"
set "folder="
for /f "tokens=* delims=" %%i in ('dir %workdir% /AD /B /TW /O-D') do (
set "folder=%%~fi"
echo %%~fi
echo robocopy %%~fi T:\Backups\!folder! /e /w:0 /r:2
goto :break
)
:break
echo newest... !folder!
for /f "skip=1 tokens=* delims=" %%i in ('dir %workdir% /AD /B /TW /O-D') do (
echo rd /s /q "%workdir%\%%~i"
)
produces:
H:\ne
robocopy H:\ne T:\Backups\H:\ne /e /w:0 /r:2
newest... H:\ne
rd /s /q "H:\LOS\DefaultChromeCopy\sdf"
rd /s /q "H:\LOS\DefaultChromeCopy\6"
rd /s /q "H:\LOS\DefaultChromeCopy\5"
rd /s /q "H:\LOS\DefaultChromeCopy\4"
rd /s /q "H:\LOS\DefaultChromeCopy\3"
rd /s /q "H:\LOS\DefaultChromeCopy\2"
rd /s /q "H:\LOS\DefaultChromeCopy\1"
So it looks like the directories that are supposed to be deleted are getting deleted, but the "newest" part is still a little wonky. I need to figure out how to get "H:\LOS\DefaultChromeCopy\ne". Right now:
%%~fi --> H:\ne
%workdir%\%%~fi --> H:\LOS\DefaultChromeCopy\H:\ne
T:\Backups\!folder! --> T:\Backups\H:\ne
T:\Backups\%folder% --> T:\Backups\
?????????????!!!!! --> H:\LOS\Default\ChromeCopy\ne & T:\Backups\ne
Fortunately, I found a sort of a workaround. There should only be 1 folder left in DefaultChromeCopy, so even though I can't figure out how to reference it, I can reference its parent. Thus, running the following deletes all but the newest folder from DefaultChromeCopy, backs DefaultChromeCopy up to T:\Backups, deletes everything in DefaultChromeCopy, backs up H:\LOS to T:\Backups, then copies DefaultChromeCopy back to H:\LOS\DefaultChromeCopy and deletes it from T:\Backups.
Here is the final working script. Thanks for everyone's help:
#echo off
echo Beginning LOS backup - deleting all Chrome backups except the newest one
if not exist "T:\Backups" md "T:\Backups"
setlocal ENABLEDELAYEDEXPANSION
set "chromebackups=H:\LOS\DefaultChromeCopy"
set "folder="
for /f "tokens=* delims=" %%i in ('dir %chromebackups% /AD /B /TW /O-D') do (
set "folder=%%~fi"
echo folder is !folder!
goto :deleteolds
)
:deleteolds
for /f "skip=1 tokens=* delims=" %%i in ('dir %chromebackups% /AD /B /TW /O-D') do (
rd /s /q "%chromebackups%\%%~i"
)
robocopy "H:\LOS\DefaultChromeCopy" "T:\Backups\DefaultChromeCopy" /e /w:0 /r:2
set topurge="H:\LOS\DefaultChromeCopy"
cd /d %topurge%
for /f "delims=" %%i in ('dir /b') do (rmdir "%%i" /s/q || del "%%i" /s/q)
setlocal DISABLEDELAYEDEXPANSION
robocopy "H:\LOS" "T:\Backups\LOS_Backup_%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%TIME:~0,2%.%TIME:~3,2%" /e /w:0 /r:2
robocopy "T:\Backups\DefaultChromeCopy" "H:\LOS\DefaultChromeCopy" /e /w:0 /r:2
rmdir "T:\Backups\DefaultChromeCopy" /s /q
start "" "T:\Backups"
echo LOS Backup has completed! You can now ZIP the folder in T:\Backups\, upload that to the LOS Repository server, and then delete T:\Backups manually.
Related
this deletes .unwanted directories from qbittorrent downloads. it works great but the esthetic side effect that I can't shake is that it echoes the file not found error if none are found.
for /f "delims=" %%u in ('dir .unwanted /a:d /b /s') do rmdir /s /q "%%u" 2>nul && if defined v%~n0 echo deleted "%%u"
Better idea is to use /D /R than /F in the For loop for Directories. Check For /? documentation.
for /d /r %%u in (.unwanted) do rmdir /s /q "%%u" 2>nul & echo deleted %%u
This is assuming you are running this from the directory of execution.
It will only echo when the directory is deleted without the ""
I have a folder That has subfolders as below : I was able to loop and copy the folder and subfolders from test1 to test 3. But I want to extend the functionality by removing the each folder after copying
but am not able to instead is removing all the test 1 to test 3 folder.The test folder is just an example, the folders can be any name.
"C:\BACKUP_FDM_FILES\localbackup\test1"
"C:\BACKUP_FDM_FILES\localbackup\test2"
"C:\BACKUP_FDM_FILES\localbackup\test3"
pushd "C:\BACKUP_FDM_FILES"
for /f "tokens=*" %%G in ('dir /b /s /a:d ') do (
echo Found %%G
XCOPY %%G "C:\FDM\Upload" /e /s /y
if errorlevel 0 (
echo Copy succesffully copied reason Files were copied without error and you can delete the content folder
rd "%%G\*" /s /q
mkdir "%%G"
)
)
popD
pause
If you resort to XCOPY, why not use the "successor" ROBOCOPY without any loop, deleting and re-creating the folder? Like in
robocopy "C:\BACKUP_FDM_FILES\localbackup\" "C:\FDM\Upload\localbackup" /s /e /COPYALL /dcopy:T /move
This will even keep the timestamp on the moved folder, and all attributes on moved files. Added benefit: you can use all the other helpful options of this command at no extra cost.
"C:\BACKUP_FDM_FILES\localbackup\test1"
"C:\BACKUP_FDM_FILES\localbackup\test2"
"C:\BACKUP_FDM_FILES\localbackup\test3"
pushd "C:\BACKUP_FDM_FILES"
for /f "tokens=*" %%G in ('dir /b /s /a:d ') do (
echo Found %%G
XCOPY %%G "C:\FDM\Upload" /e /s /y
if errorlevel 0 (
echo Successfully copied now you can delete folder
popd
rd "%%G\*" /s /q
mkdir "%%G"
)
pause
You are using pushd to go to backup folder so you need to use popd to go back to parent folder.
SS64 - POPD
I'm writing a simple .bat backup script, and as part of it I want the oldest backup (folder) to be deleted upon reaching a set max limit of backups.
Right now I have this:
%COUNTER% is based on the number of backup folders currently in the directory where backups are stored, and is calculated earlier in the script.
%MAXBACKUPS% is just a user-specified number like "10," to say that you only want to keep up to 10 versions of the backups.
:: Delete the oldest backup, but only if we've exceeded the desired number of backups.
IF %COUNTER% gtr %MAXBACKUPS% (
ECHO More than %MAXBACKUPS% backups exist. Deleting oldest...
FOR /f "delims=" %%a in ('dir "..\Backup\*" /t:c /a:d /o:-d /b') do rd /s /q "..\Backup\%%a"
::Increment the counter down since we've just removed a backup folder.
SET /a COUNTER=%COUNTER%-1
)
I would like this script to only delete the one oldest folder in the ..\Backup folder, but as it stands it seems to delete every single folder it finds once it reaches the backup limit, which is obviously not the desired behavior.
You were so close ! :-)
All you need to do is skip the first %MAXBACKUPS% entries when sorted by date descending. You don't even need your COUNTER variable.
:: Preserve only the %MAXBACKUPS% most recent backups.
set "delMsg="
for /f "skip=%MAXBACKUPS% delims=" %%a in (
'dir "..\Backup\*" /t:c /a:d /o:-d /b'
) do (
if not defined delMsg (
set delMsg=1
echo More than %MAXBACKUPS% found - only the %MAXBACKUPS% most recent folders will be preserved.
)
rd /s /q "..\Backup\%%a"
)
A simple way to do this based on your script:
FOR /f "delims=" %%a in ('dir "..\Backup\*" /t:c /a:d /o:-d /b') do set lastfolder=%%a
rd /s /q "..\Backup\%lastfolder%"
So you still loop over each folder, sorted by age, but you overwrite %lastfolder% so at the end it contains only the name of the oldest folder.
Then you delete that folder.
Here's the final block of code I ended up using:
:: Preserve only the %MAXBACKUPS% most recent backups.
FOR /f "skip=%MAXBACKUPS% delims=" %%a in (
'dir "..\Backup\*" /t:c /a:d /o:-d /b'
) do (
ECHO More than %MAXBACKUPS% backups found--Deleting "%%a".
ECHO.
rd /s /q "..\Backup\%%a"
)
It simplifies the deletion message code a bit, and provides the end user with info about what file was deleted in the command prompt window.
Based on dbenham's answer.
FOR /f "delims=" %%a in ('dir "..\Backup\*" /t:c /a:d /o:d /b') do (
rd /s /q "..\Backup\%%a"
goto :break
)
:break
you can break the for loop with goto
I want to use this script below to clean out "tmp" and "cache" folders in websites like "C:\Storage\Websites\Site1".
It tries to delete files and subfolders in "C:\Storage\Websites\Site1\tmp" and "C:\Storage\Websites\Site1\cache".
Which is right, but it also tries to delete files and subfolders in, for example, "C:\Storage\Websites\Site1\MySpecialLittleProgram\tmp" and, for example, "C:\Storage\Websites\Site1\MySpecialLittleProgram\cache".
Which is wrong. It should only clean up the "tmp" and "cache" folder in the root of the website and not in other subfolders.
If I delete the /s parameter in 'dir /a:d /b /s tmp cache' it will not find anything.
How can I do this part?
(I have deleted the /q parameter in the file deleting part and the folder removing part if anyone copies my script.)
#echo off
call:CleanUp "C:\Storage\Websites"
echo.&pause&goto:eof
::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------
:CleanUp
IF EXIST %~1 (
cd /d %~1
FOR /f "tokens=*" %%i in ('dir /a:d /b /s tmp cache') DO (
echo %%i
::DELETING FILES I FOLDERS AND SUBFOLDERS
del %%i /s
::DELETING NOW EMPTY FOLDERS AND SUBFOLDERS
FOR /D %%p IN ("%%i\*.*") DO rmdir "%%p" /s
)
)
goto:eof
UPDATE:
I updated my code to be (it is working now):
#echo off
call:CleanUp "C:\Storage\Web"
call:CleanUp "C:\Storage\Web-IIS"
goto:eof
::--------------------------------------------------------
::-- Function section starts below here
::--------------------------------------------------------
:CleanUp
IF EXIST %~1 (
cd /d %~1
FOR /f "tokens=*" %%i in ('dir /a:d /b') DO (
IF EXIST %%i\tmp (
del %%i\tmp /s /q
FOR /D %%p IN ("%%i\tmp\*.*") DO rmdir "%%p" /s /q
)
IF EXIST %%i\cache (
del %%i\cache /s /q
FOR /D %%p IN ("%%i\cache\*.*") DO rmdir "%%p" /s /q
)
)
)
goto:eof
This should remove the files in those two locations:
#echo off
del "C:\Storage\Websites\Site1\tmp\*.*" /a /s
del "C:\Storage\Websites\Site1\cache\*.*" /a /s
From your comment, this may be what you need to do: remove the echo keyword after testing it to see the commands on the console that would be executed.
#echo off
cd /d "C:\Storage\Websites"
for /d %%a in (*) do (
for %%b in (tmp cache) do (
pushd "%%~fa\%%b" 2>nul && (echo rd /s /q "%%~fa\%%b" 2>nul & popd)
)
)
pause
I suggest to use rmdir or rd for this task:
rd "C:\Storage\Websites\Site1\tmp" /S /Q
md "C:\Storage\Websites\Site1\tmp"
rd "C:\Storage\Websites\Site1\cache" /S /Q
md "C:\Storage\Websites\Site1"
Command rd with options /S for all subdirectories and /Q for quiet deletes also tmp and cache, but those 2 directories can be easily recreated using command md although I'm quite sure that this would not be really necessary here as the application creating tmp and cache would do it also automatically.
If that is not what you want, please show as directory listings with files and folders in one of the two directories before cleanup and after cleanup.
I need to copy files from recent build folder to another folder used for testing. I'm having a hard time getting the name of the most recent build folder.
My current attempt is this:
#for /D %%i in ('dir e:\builds\projectA\* /O:D') do set target=%%i
echo %target%
xcopy "%target%\*.*" \\devbox\projectA /y /s
I was hoping target would be the newly created folder from which I could then copy the files from. However, when I echo target to the console it just says:
/O:D'
Does anyone know how I can get this to work (or know of an alternative)?
Replace the /D with /F and add /B to the bracketed dir command.
#for /F %%i in ('dir e:\builds\projectA\* /O:D /B') do set target=%%i
echo %target%
xcopy "%target%\*.*" \\devbox\projectA /y /s
pushd E:\builds\projectA
for /f "delims=" %%d in ('dir /b /a:d /o:d') do #echo %%d>latest.txt
for /f "delims=" %%l in (latest.txt) do xcopy "%%l\*.*" \\devbox\projectA /y /s
del latest.txt
popd