robocopy command to move file based on created date - batch-file

I have files in a folder 'FILEPATH', each file has different created date and modified date(modified date is less than created date).
I want to delete the files with created date greater than 10days. I used below command but it works on modified date.
ROBOCOPY %FILEPATH% %DUMPFOLDER% /move /minage:10
del %DUMPFOLDER% /q
On some forums its written that minage refers to created date but it's referring to modified date while executing. Am I doing something wrong here? Or is there any other alternate.

Unfortunately, there's no easy way to do this. The only commands of which I'm aware that can deal with file creation dates are dir /t:c and wmic datafile. There could be others, but there are none that simplify performing date math as forfiles or robocopy do.
Since date math in batch is cumbersome anyway, in this situation it makes sense to borrow from another runtime environment -- PowerShell, for example, or VBScript or JScript. The Windows Scripting Host FileSystemObject's File Object has properties for DateCreated, DateLastAccessed, and DateModified. With JScript, getting a file's age based on its DateCreated property is simply a matter of JavaScript Date() arithmetic.
Here, salt this .bat script to taste:
#if (#CodeSection == #Batch) #then
#echo off
setlocal
set "FILEPATH=c:\path\to\whatever"
set "age=10"
for %%I in ("%FILEPATH%\*") do (
call :getAge result "%%~fI"
setlocal enabledelayedexpansion
if !result! gtr %age% (
echo %%~nxI created !result! days ago and should be deleted
rem del "%%~fI"
) else (
echo %%~nxI is new ^(created !result! days ago^)
)
endlocal
)
goto :EOF
:getAge <return_var> <filename>
for /f "delims=" %%I in ('cscript /nologo /e:Jscript "%~f0" "%~2"') do set "%~1=%%I"
goto :EOF
#end
// JScript portion
var fso = WSH.CreateObject('scripting.filesystemobject'),
created = fso.GetFile(WSH.Arguments(0)).DateCreated,
age = new Date() - created;
WSH.Echo(Math.floor(age / 1000 / 60 / 60 / 24));
If you want something simpler, you could employ wmic datafile and get the first 8 digits of get creationdate like this cat does, but his solution doesn't take into account time of day. Such a method might inappropriately delete files that are 9 days, 23 hours old. Then there's also the problem of calculating days across new months. The JScript method above tests file age based on the current moment, rather than based on midnight; and will handle spanning months, years, and leap years with no conscious effort.

Related

Batch file to delete files older than N hours or minutes

I see this - Batch file to delete files older than N days
But how can I delete files older than N hours or minutes?
Thanks.
Neither of the solutions here worked for me. They are very innovative solutions, and the first one (.net/FileTimeFilerJS.bat [sic]) actually worked once for me. When I tried to call it on another folder, however, it simply crashed. I tried the second one (jscript/FileTimeFilterJs.bat), but it did not successfully delete all files older than one hour.
My solution requires an executable, but I found it was the best solution for me.
I downloaded FindUtils from GnuWin32, and extracted 3 files (you have to download the two zips below): libintl3.dll, libiconv2.dll, and find.exe (combined they are about 1MB in size). I rename find.exe to gnu_find.exe just to avoid the Windows FIND command.
Then, you can run the beautiful GNU command (below command is for all zip files older than 120 minutes in folder specified by environment variable %fldr%):
gnu_find %fldr% -name *[.:]zip -type f -mmin +120 -delete
Instead of *.zip, I use *[.:]zip, because Windows 7+ will expand the *.zip before find can use it.
Find Utils bin
Find Utils deps
Its challenging to do this (independent of time date settings) even with WSH\Jscript\VBscript as WSH does not return date object when you request the date/time properties of a file ,but a string that depends on time settings (wmi could be used but this will hit the performance).
I suppose you have installed .net framework which make the task far more easier.
Here's a hybrid tool that should work in your case. You can save it with whatever name you want. Here's how to use it (its called FileDateFilterJS.bat in this example):
#echo off
for /f "tokens=* delims=" %%# in ('FileDateFilterJS.bat "." -hh -5') do (
echo deleting "%%~f#"
echo del /q /f "%%~f#"
)
pause
Where the hours are 5 - -hh -5 and directory is current - "." .You can remove the echo before del command.
This script took me far more time than I've expected (despite I've researched the topic and has some parts ready) and is no so heavy tested so probably is still not buggy-free.And I suppose the help message and options could be improved.
#echo off
cd /d "your file path"
:: delete files 3 hours ago. If you want other condition, refer https://www.w3schools.com/asp/func_dateadd.asp
echo wscript.echo dateadd("h",-3,now())>GetOldDate.vbs
for /f "tokens=1,2 delims= " %%i in ('cscript /nologo GetOldDate.vbs') do (
set d=%%i
set t=%%j
)
echo "%d%"
echo "%t%"
for /f "tokens=1,2,3 delims=/" %%a in ("%d%") do (
set y=%%a
set m=%%b
set d=%%c
)
for /f "tokens=1,2,3 delims=:" %%a in ("%t%") do (
set h=%%a
set mm=%%b
set s=%%c
)
if %m% LSS 10 set m=0%m%
if %d% LSS 10 set d=0%d%
if %h% LSS 10 set h=0%h%
if %mm% LSS 10 set mm=0%mm%
set OldDate=%y%/%m%/%d% %h%:%mm%
echo "%OldDate%"
del GetOldDate.vbs
for %%a in (*) do (
if "%%~ta" lss "%OldDate%" (
echo %%a
echo "%%~ta"
del %%a
)
)
Deleting files:
#echo off
echo >%temp%\temp.vbs for each File In CreateObject("Scripting.FileSystemObject").GetFolder("[path_file]").Files
echo >>%temp%\temp.vbs If DateDiff("n",File.DateCreated,Now) ^> 30 Then File.Deletee
echo >>%temp%\temp.vbs next
cscript /nologo %temp%\temp.vbs
Exit /b
Deleting folders:
#echo off
echo >%temp%\temp.vbs for each Folder In CreateObject("Scripting.FileSystemObject").GetFolder("[Path_folder]").subFolders
echo >>%temp%\temp.vbs If DateDiff("n",Folder.DateCreated,Now) ^> 30 Then Folder.Delete
echo >>%temp%\temp.vbs next
cscript /nologo %temp%\temp.vbs
Exit /b
To vary the time difference, we need to substitute in DateDiff("n",[Folder or File].DateCreated,Now) ^> 30, the condition (in this case 30 minutes).
.DateCreated can be changed by: .DateLastAccessed or .DateLastModified.
Time difference: "yyyy" Year, "m" Month, "d" Day, "h" Hour, "n" Minute, "s" Seconds.
["Path_file o Path_folder"] has to be sustituded for the target file or folder.
Here's another script that relies only on WSH/JSCRIPT and almost the same interface (and does not require .net installed).To show files older than 5 hours use:
FileTimeFilterJS.bat "." -hh -5 -filetime modified

Compare current date with file modified date in batch file

I have a requirement to create a batch file and that should work in windows 2003 server.
I have source folder "c:\Source" and destination folder "c:\Destination".
I want to check all the file modified dates in source folder:
If the file modified date is less than current date then that file will move into destination folder
Otherwise, do nothing.
Note: as my server is production server so, I am unable to install Resource kit and robocopy.exe. The only way is write the batch script.
Robocopy and forfiles are not working in Windows2003 server.
Update
Since you have forfiles on your server, this is easy. To check for files older than 1 day old, just use forfiles /D -1. For files over 2 days old, /D -2.
forfiles /D -2 /M *.log /P C:\Source /C "cmd /c move #file c:\Destination"
Enter forfiles /? in a console window for full syntax.
Original answer
Consider revising your requirement. Instead of saying "If file modified date is less than the current date", you should say, "If file modified date does not equal current date". That absolves you from having to do date math, and makes your task profoundly simpler. After all, the last modified date is not going to be a date in the future, right?
After that, it's a simple matter of scraping today's date from %date% and comparing it with the date from each file's %%~tX substitution property in a for loop. Type help for in a console window and see the last two pages for more information about this syntax.
I don't think there will be any locale date formatting issues with this. As long as your system's %date% variable is in the format of dayOfWeek Date and %%~tX is formatted as Date Time etc. then this script should work regardless of whether you handle dates locally as MM/DD/YYYY or YYYY/MM/DD or DD/MM/YYYY or something else. I hope.
#echo off
setlocal enableextensions
set "source=c:\Source"
set "destination=c:\Destination"
:: store today's date in %today%
for /f "tokens=2" %%I in ('echo %date%') do set "today=%%I"
for %%I in ("%source%\*") do (
rem :: scrape MM/DD/YYYY from %%~tI
for /f %%a in ('echo %%~tI') do (
rem :: compare the two dates
if "%%a" neq "%today%" (
echo %%~nxI: %%a does not equal %today%. Moving.
>NUL move /y "%%~fI" "%destination%"
) else (
echo %%~nxI: %%a equals %today%. Skipping.
)
)
)

Get date from file name and check age

I will have a variable that will be equal to anything from 1-7, which will represent 1 day old and so on. I need to find a file that is the same age in days as that variable.
For example
set "age=4"
// code to find the file OR folder that is 4 days old
It's worth noting that I need to get the filename of this file
Here, try this:
#echo off
setlocal
set age=4
set /a maxage=age+1
:: For files that are %age% days old or older, set a variable
for /f "delims=" %%I in ('forfiles /d -%age%') do (
set "fileArr[%%~snxI]=%%~fI"
)
:: for files that are %age% + 1 days old or older, unset variable
for /f "delims=" %%I in ('forfiles /d -%maxage%') do (
set "fileArr[%%~snxI]="
)
:: Get values of all remaining fileArr variables
for /f "tokens=1,* delims==" %%I in ('set fileArr') do echo(%%J
As you can see from the comments, first the script gets all files %age% days old or older, and sets a variable. To make the variable name unique and to be able to index it later, the variable name contains the short filename, simulating an associative array. Next, it unsets those variables which are %age% + 1 days old or older, then outputs what's left.
No painful date math is needed. forfiles handles the computation. If you needed age-by-minutes computation, admittedly that gets a little more complicated; but forfiles handles math by day just fine.
I found a much easier soloution:
ROBOCOPY "D:\file-backups\%ThisUser_Username%\Server"^
"%ThisService_WorkingDirectory%#DayZ_Epoch_Server\Addons"^
"dayz_server_*.pbo"^
/minage:%ThisService_filerestoreage%^
/maxage:%ThisService_filerestoreage%
In batch, as soon as you get the date of modification which corresponds to the age, (thus %DATE% - %AGE%), you can use the ~t modifier in a parameter expansion to get the age of the file.
Note that if you have PowerShell on your system (and you really should because it's preinstalled since Win7, cf comments) you can use it to do the date calculation easily.
Hence, a script that does what you want (with the parameter being %age% which you can replace with a command-line parameter for example) :
set age=4
for /f "delims=|" %%i in ('powershell.exe -Command "Get-Date -Format dd/MM/yyyy -Date ([DateTime]::Today.AddDays(-%age%))"') do set age_date=%%i
echo Files modified %age% days ago (the %age_date%) are :
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=|" %%f in ('dir /b') do (
set file_date=%%~tf
if "!file_date:~0,10!"=="%age_date%" (echo %%f)
)
For a pure-batch script to get the date to replace the powershell call (say for legacy versions), you could slightly modifiy the code from here : http://www.powercram.com/2010/07/get-yesterdays-date-in-ms-dos-batch.html , even though that would get very ugly.
In contrast, unix-like systems have a tool for this, see man find, which is more user-friendly.
find /path/to/parent/directory -daystart -atime $age
atime : File was last accessed n*24 hours ago
$age without leading + or - : find exactly age of $age*24 hours (as opposed to less or equal, or superior or equal)
daystart :
Measure times (for -amin, -atime, -cmin, -ctime, -mmin, and
-mtime) from the beginning of today rather than from 24 hours
ago
You can use mtime instead of atime for modified date instead of creation date.

Batch File to Delete Files in a Folder

I understand that there are tons of questions on this site regarding the creation of a batch file that goes through the file in a specified folder and deletes them if it satisfies the condition stated.
However, I would like to tweak that a little bit. In my batch file, I would like to look at a folder, say C:\Dev and get all the files that are within the same month. After getting all those files, I want to sort through all the dates and delete everything except for the latest one. So if I have 5 files for January on that folder with dates January 1, 12, 20, 27, and 30, I would only keep the file dated January 30th and delete all the others.
Is this possible?
< lang-dos -->
#ECHO OFF
SETLOCAL
SET "targetdir=c:\sourcedir"
SET "pfname="
PUSHD "%targetdir%"
FOR /f "delims=" %%a IN ('dir /b /a-d /o:d "*" ') DO (
SET "fname=%%a"
SET "fdate=%%~ta"
CALL :process
)
POPD
GOTO :EOF
:process
:: reformat date - this depends on yout local date-format.
:: YY(YY)MM required - my format is dd/mm/yyyy
SET fdate=%fdate:~6,4%%fdate:~3,2%
IF NOT DEFINED pfname GOTO nodel
IF %fdate%==%pfdate% ECHO DEL "%targetdir%\%pfname%"
:nodel
SET pfdate=%fdate%
SET "pfname=%fname%"
GOTO :eof
This should work for you. The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO DEL to DEL to actually delete the files.
First, the target directory is set up and pfname is cleared.
The PUSHD changes the current directory until the POPD is executed
the dir command outputs filenames only (/b), no directory names (/a-d) in date-order (/o:d). Each line sets fname to the filename and fdate to the filedate.
within :process, the date-string is manipulated. I don't know which format you use, but the basic formula is %variable:~startposition,length% where startposition starts at 0=first character. The idea is to have fdate in the format yyyymm
if pfname (previos filename) is not set, this is the first file found, so we don't delete that.
For every other file, if the filedate is the same as the previous filedate, then delete the previous filename.
The current filename/date is then recorded as the previous version.
Done!

Create bat or script file to delete files

I would like to know how to create a bat file which on its first run would store the system date and on subsequent run delete a particular file 30 days later.I think if a bat file can be created that would store system date on its first run and the second bat files reads the first file for the date would be better.But how?
As #devio commented, PowerShell is definitely more fully featured: PowerShell Quick Reference
If it has to be a Batch file, this reference explains most commands.
I love powershell, and it is certainly more powerful than batch files, but for this it shouldnt really matter what you use, so if you're comfortable with your batch files you should be able to stick with them.
The only way you'll be able to later recover that date is to store it somewhere (or have your task running the whole time which is unrealistic - think reboots among other things)
You could write the deletion date to the registry or a text file or somewhere else that is 'known', but then you need to have something else running to check 'if its time to act'.
I'd be inclined to just create a scheduled task for the delete during the original script so that I wouldn't have to check up on it. You could even have the delete script you've scheduled clean up the task when it's done.
You could use something like a windowscripting host vb script or js script file. Also scripting languages such as php, python or perl would allow you to do something like this easily and possibly give you much greater flexibility than a shell script.
It's going to take a while to answer this one, but here's the first thing to suggest.
When you want to have a single .BAT (or .CMD) which does something and also does something later based on the first something, one can use the "flag parameter" technique. For example, in a script which accepts a wildcarded list of files to manipulate one could do as follows:
::foo.cmd
#echo off
if %1#==# goto fail
set f=%1
if %1==! goto inner
for %%x in (%f%) do cmd /c %0 ! %%x
goto done
:inner
set f=%2
echo do something with %f%
goto done
:fail
echo %0 {wildcard}
:done
The script is actually written such that it can be called anything, and it will call itself (using %0).
Now how to do date arithmetic is going to take some time to figure out. I hope that much at least gets you started in the right direction.
my setup after after completion of installation would run a bat file(once) that should get the system date(install date) and store in a text file.the main program would be called by another batch file that would read the text file every time for the date assisting it to delete particular files after "N" number of days referencing the install date in the text file.
HI MARK BRACKETT,
when I run batch1 the date is MM\DD\YYYY.But when I run batch2 the startdate is DD and the startmonth is also DD.The final equation is if rundate==nowdate execute command,it should be rundate=>nowdate,cause if pc not switched on rundate.secondly months with 31days the rundate would 31st next month
VBScript, PowerShell, or C# (I use CS-Script to run my C# scripts) would be much cleaner - but sometimes I enjoy a little batch file challenge.
So - this is for 1 month from the current date and time, but it gives you the idea. To actually figure 30 days, I suspect you'd need about 50 lines of IF statements. Or, a single external EXE to calculate it for you.
I think there's a cleaner way to use SET itself to split out the date parts, which would cut this down by about 3 lines - but I don't recall the syntax ATM.
Batch1
ECHO %DATE% > start.txt
Batch2
: Get start date
FOR /F "tokens=1* delims= " %%i IN (start.txt) DO set startDate=%%j
FOR /F "tokens=1,2 eol=/ delims=/ " %%i IN ('echo %startDate%') DO set startMonth=%%i
FOR /F "tokens=1,2 delims=/ eol=/" %%i IN ('echo %startDate%') DO set startDay=%%j
FOR /F "tokens=2,3 delims=/ " %%i IN ('echo %startDate%') DO set startYear=%%j
: Get run month and day as YYYY-MM-DD
SET /A runMonth=%startMonth% + 1
IF %runMonth% LEQ 10 SET runMonth=0%runMonth%
SET runDay=%startDay%
SET runYear=%startYear%
SET runDate=%runYear%-%runMonth%-%runDay%
: Get current month and day as YYYY-MM-DD
FOR /F "tokens=1* delims= " %%i IN ('echo %DATE%') DO set nowDate=%%j
FOR /F "tokens=1,2 eol=/ delims=/ " %%i IN ('echo %nowDate%') DO set nowMonth=%%i
FOR /F "tokens=1,2 delims=/ eol=/" %%i IN ('echo %nowDate%') DO set nowDay=%%j
FOR /F "tokens=2,3 delims=/ " %%i IN ('echo %nowDate%') DO set nowYear=%%j
SET nowDate=%nowYear%-%nowMonth%-%nowDay%
: Compare
IF %nowDate% GEQ %runDate% ECHO Delete!
Note that this doesn't handle year changes appropriately (it'll delete on the year change).

Resources