I'm trying to create a batch script that will delete all sub directories which are older than 30 days.
I'm really new to batch scripting so I'm just hoping that someone can help me out on this.
I was able to find a script that delete all sub directories in specified location.
#for /f "tokens=*" %%a in ('dir /s /b "C:/temp/test" 2^>NUL') do rd /s /q "%%a"
Can someone tweak this script so it deletes only directories which are 30 days old?
I think FORFILES is going to do it...
FORFILES -D 30 will iterate all files last modified over 30 days ago
So, something like...
FORFILES /S /D -30 /C "cmd /c IF #isdir == TRUE rd #path"
Should (untested) recursively remove all folders older than 30 days :)
Btw - Check out http://ss64.com/nt/ for more command line goodness
This is working fine for me:
Posted by Matt Roberts --> FORFILES /S /D -30 /C "cmd /c IF #isdir == TRUE rd #path"
Be careful when you start the ".bat" file with "Run as administrator", it's not using the current location of the file it takes this location --> "C:\Windows\system32"
For savety reasons add the /P "C:\temp"
FORFILES /P C:\temp /S /D -30 /C "cmd /c IF #isdir == TRUE rd #path"
Assuming you are restricted to batch files... check this - but if you can use VBScript, I think you can do a bit better.
Now that you have clarified your real problem, please understand that if you meant to use System.exec() you will have to contend with plenty of drawbacks.
Alternatively if you really want to use JNDI (you mention "native" but don't make clear what you mean) maybe this will be of help: http://mindprod.com/products1.html#FILETIMES
Do you have powershell on your system?
dir | ? { $_.LastWriteTime -lt [DateTime]::Now.AddDays(-30) } | % { rm $_.FullName }
I know this is an older topic; however, I was recently looking to do this and was able to by building off of what Matt Roberts suggested. I used the following FORFILES syntax:
FORFILES /P \path\to\dir /S /C "cmd /c IF #isdir == TRUE rmdir /S #path /Q" -D -30
You will need to replace \path\to\dir with the path (including drive letter) to the directory (/P) you want to run this on. This will then recursively (/S) search through the directory and run (/C) rmdir (again recursively). Without /Q you are asked if you want to delete each dir/file so if you are planning on running this silently in a script you will need to have it. You can change the amount of days (-D) by changing -30 to something else.
I then used Task Scheduler to automate this once every week (confirmed working). To make sure it works, set the task with 'run with highest privileges'
Note: This setup will irrevocably delete the files. They will not appear in your recycle bin. So once they are gone they're gone (unless you have backups).
You might want to consider using Windows Script Host, in which you could run a VBScript to do just that. Think of it like a batch file with more flexibility and power.
See http://www.computing.net/answers/programming/wsh-delete-files-in-folder-by-date/16255.html
This is not going to be a simple tweak. As it stands, there is no easy way (that I know of) to do the date-diff operation in the cmd interpreter.
First you'll have to parse the current date:
C:\>date /T
Thu 08/05/2010
Once you have the day, month, year, you have to get the date for each item in the directory listing, which you can do by removing the /b param in the dir command and modifying the tokens line to give you tokens 1 and 4, i.e. tokens=1,4, and then doing the date math yourself, which will be a pain because you have to handle different lenght months, and December -> January transitions (new years), etc, and you're almost certain to get it wrong.
Also add the /ad param to get just directories.
I would recommend using PowerShell or some other scripting technology that gives you the tools you need to manipulate dates.
Related
I'm trying to create a batch file in Win7 that will copy any files that have been created or modified today and copy them to a destination with a similar directory structure. This is what I have so far:
set today="20180721"
robocopy "C:\temp\" "D:\backup\temp\" *.* /s /DCOPY:T /MINAGE:%today%
I know that /e copies empty directories and /xf excludes all files, but I'm not sure if that helps me. The code above seems to copy all files regardless of date, so I'm a little lost here.
Assigning quotes to your variables is not a best practice and will cause problems with some commands if you try to quote the variable later on. Regardless that was not your problem. Your problem is you need to use the /MAXAGE option. Reading the help file you should see this:
/MAXAGE:n : MAXimum file AGE - exclude files older than n days/date.`
So your code should be:
set "today=20180721"
robocopy "C:\temp\" "D:\backup\temp\" *.* /s /DCOPY:T /MAXAGE:%today%
Going to assume you thought the options were for INCLUDE.
robocopy's /MINAGE//MAXAGE options regard the full date and time, so specifying something like /MAXAGE:1 filters for files that have been modified within the last 24 hours.
If you want to process files which have been modified today only, hence regarding the date but not the time, you could use forfiles and its '/D' option, like this:
set "DEST=D:\backup\temp"
forfiles /P "C:\temp" /D +0 /C "cmd /C if #isdir==FALSE for %%Z in (#relpath) do #(2> nul md 0x22%DEST%\%%~Z\..0x22 & copy #relpath 0x22%DEST%\%%~Z0x22)"
what I would like to accomplish is have a three day rolling backup of the Source Folder, which will be modified every day. I want anything removed longer than 3 Days as worst case I will have to revert to the most recent backup but having that 3 Days allows me to revert back to a previous changes if need being.
What I have done in Command Line is as follows:
SET STAMP=%DATE:/=-% %TIME::=.%
SET SOURCE="C:\Users\PersonA\Documents\Test\Source"
SET DEST="C:\Users\PersonA\Documents\Test\Destination\%STAMP%"
robocopy %SOURCE% %DEST% /e
forfiles -p "C:\Users\PersonA\Documents\Test\Destination\" -s -m *.* -d -3 -c "cmd /c echo #file"
I have timestamped and concatenated the FolderName and Current Date and Time.
However the bit I am struggling with his removing anything longer than 3 Days, currently the process is just copying, but what I need is a process to detect modified date or perhaps created date and remove directory anything greater than 3 days with the code I produced. The deleted command I have added above doesn't seem to do anything at all.
If anyone can help I will be most grateful.
Thank you in Advance
I would recommend something like this:
SET STAMP=%DATE:/=-% %TIME::=.%
SET SOURCE="C:\Users\PersonA\Documents\Test\Source"
SET DEST="C:\Users\PersonA\Documents\Test\Destination\%STAMP%"
REM Set Robocopy to only retry once after waiting 1 second; copy all
REM file attributes, security, etc; and create a log file in the
REM temp folder with the same name as the date.
robocopy %SOURCE% %DEST% /e /r:1 /w:1 /COPYALL /LOG:%TEMP%\%STAMP%.LOG
C:
CD \Users\PersonA\Documents\Test\Destination\
REM Recursively and quietly delete all directories older than
REM 3 days
FORFILES /S /D -3 /C "cmd /c IF #isdir == TRUE rd /S /Q #path"
This is extrapolated from the answer given in this post.
I cant get FORFILES to work for me. I run a .bat that backs up a few databases I have each day using this one example below.
COPY "X:\W Attendenance\C Crew Attendance\Attendance Control DB v4.xx.accdb" "X:\Supervisors Log\Backups\Attendance Bak\bak_%currdate%_Attendance Control DB v4.xx.accdb"
Then after running my backups I wanted to delete the old files that were older than five days by using the below example.
FORFILES /p "X:\Supervisors Log\Backups\Attendance Bak\" /d -5 /c "cmd /c del #path "
But what happens is it creates the backups but never deletes the old ones. What am I doing wrong?
Ken it still seems to not work. I changed the #file to #path and ran and I still have my backups. I also had another question, can I limit the delete to just files starting in bak_ ? and can I delete the file by its name because every backup starts with bak_ then the date mm-dd-yyyy_ then name of the file...
This fixed it... Thanks for your help and links!
forfiles -p "X:\Supervisors Log\Backups\Attendance Bak" -s -m *.* -d -1 -c "cmd /c del #path"
On a side note that only is able to delete the File but Sometimes I needed to delete a folder and everything in it so I use:
FORFILES /P "H:\BACKUPS\bk_Operator_Rate_Program" /d -10 /c "cmd /c IF #isdir == TRUE rd /S /Q #path"
I'm a bit of a newbie with batch files, but am looking for a script to delete .txt log files that are older than 30 days... (FWIW, I am on XP SP3...)
I tried to follow the example found here, (including downloading the forfiles.exe from here) and ended up with this:
forfiles -p"D:\SQL Database Back Ups\Update_FmlaManagement_Log" -s -m *.txt -d-30 -c "cmd /c del #FILE"
But I get this error:
Error path not found (3rd argument) line 545
I did a lot of googling, but can't seem to figure out what this error is talking about. Somebody suggested using forfiles.exe in order to get the #variables to work, but I tried that (along with the full forfiles path), and nothing seems to be working...
Can someone at least point me in the correct direction as to what this error message is telling me?
Just to see whether I could, I cobbled a little sumn sumn together to delete files older than 30 days old without using forfiles. Make sure the pushd line is set to go to the appropriate directory. I got the 2592000 by subtracting 01/01/2013 from 01/31/2013.
#echo off
setlocal enabledelayedexpansion
pushd "D:\SQL Database Back Ups\Update_FmlaManagement_Log"
set today=%date:~-10%
call :toEpoch %today%
set /a thirtyDaysAgo=%epoch% - 2592000
for /f "tokens=1,5*" %%I in ('dir /o:d *.txt ^| findstr "txt$"') do (
call :toEpoch %%I
if "%%K"=="" (set file=%%J) else (set file=%%J %%K)
if /i %thirtyDaysAgo% GTR !epoch! del /q "!file!"
)
popd
goto :EOF
:toEpoch date
echo wscript.echo datediff("s", "01/01/1970 00:00:00", "%1")>epoch.vbs
for /f %%x in ('cscript /nologo epoch.vbs') do set epoch=%%x
del /q epoch.vbs
goto :EOF
(VBscript borrowed from Cameron Oakenleaf.)
Admittedly, this won't work obsessively accurately. For instance, if a log file was last modified at noon 30 days ago and you're running this at 8:00 am, the file will probably be deleted even though it still has another 4 hours to go to reach 30 days old. And it's probably not nearly as efficient as forfiles.exe.
*shrug* It was a road less traveled and I traveled it.
EDIT: HerbCSO has another, probably better implementation that makes mine look like a Rube Goldberg-ian solution.
#file is only the File name. It does not include the path. If your batch file is not being executed within your path it will not see the file to delete it because you are in a different working directory.
I can't believe that the error comes from your sample line.
My forfiles (Win7) throws an error for the missing space between -p and the path.
And the text of the error message isn't normal for batch commands.
I don't know any batch command that tells you the line where an error occours, nor which parameter is wrong.
So I believe you got the error message from a completly different source.
Or you have a second forfiles command that do some totally other thing.
Or do you named one of your tests forfiles.bat?
Well, I'm not positive, but it seems the issue might have been a bad forfiles.exe from Microsoft's FTP server. I ended up downloading a second forfiles.exe (for Windows Server 2003) from this guy's site (direct download).
After replacing the original exe in C:\WINDOWS\system32 and getting rid of the copy in my downloads folder, I changed the syntax a little from the dashes to forward slashes as follows:
forfiles /p "D:\SQL Database Back Ups\Update_FmlaManagement_Log" /s /m *.txt /d -30 /c "cmd /c del #FILE"
and this worked perfectly first try!
So I guess the answer is, don't download forfile.exe from Microsoft's FTP server? :P
EDIT:
I would be very interested to know if other people have successfully used Microsoft's .exe in the link above? Otherwise maybe it's just something with my particular setup...
I have written code in window batch file (eq. getFiles.bat ) that get all files within select date range.
eq.
xcopy /S /D:01-10-2011 *.* C:\todaysFiles
But I want get all files in between two dates including From date and To date.
file extension is .cmd or .bat
If you're on Vista/Win7/WinServer2008 you can use robocopy like so:
robocopy c:\source c:\destination *.* /MAXAGE:20101231 /MINAGE:20111001
On XP, I'm not sure if there are built-in solutions short of using Powershell and the like.
The title of this question is slightly misleading. Based on the questioner's xcopy example, I believe the questioner wants to know "How to copy all files created...", not how to get all files (which I equate with list).
The questioner also states "file extension is .cmd or .bat". This could mean that the questioner wants to copy only files with these extensions but I think it means the questioner would like a batch script solution.
To use the following solution, open a command prompt and chdir to the folder where the files to be copied are located. Then enter the commands listed below, changing the SET values as appropriate.
SET DESTINATION=C:\destination
SET DATE_FROM=01/01/2005
SET DATE_TO=01/01/2007
> nul forfiles /S /D +%DATE_FROM% /C "cmd /C if #isdir==FALSE 2> nul forfiles /M #file /D -%DATE_TO% && > con ( echo #path && copy /V #path %DESTINATION% )"
Note: this will copy files in subfolders as well as files in the top-level folder.
The SET values could be hard-coded directly into the > nul forfiles... line, meaning only one line is required, but for clarity I've used variable substitution.
A caveat is that it is based on date modified (original question asked for date created)
Credit to aschipfl (https://stackoverflow.com/a/36585535/1754517) for providing the inspiration for my answer.
You can also use the forfiles command. It can search recursively in all subfolders /s for files created in the selected root folder /p <Path>, execute commands on the selected files /c "<Command>", apply masks to search /m <SearchMask>, between a date range /d [{+|-}][{<Date>|<Days>}]
more info here, and here
Here's a batch for viewing files by creation date by year. Easily changed to cmd prompt by removing the extra percentage symbols.
for %%a in (2011 2012 2013 2014 2015 2016 2017) do (
for /f %%i in ('xxcopy i:\podcasts\*.* /LL /ZS /Q /FC /DA:%%a-01-01 /DB:%%a-12-31 ^| find /c /v ""') do echo %%a: %%i
)