Create bat or script file to delete files - batch-file

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).

Related

batch file to read a log file and count the number of users logged In on a particular day

I have a log file where the user login details are stored in below format:
INFO ;servername;2016-02-16 01:50:12,user4#COM;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
INFO ;servername;2016-02-16 01:50:12,user3#COM;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
INFO ;servername;2016-02-17 01:50:12,user1#COM;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
INFO ;servername;2016-02-18 01:50:12,user2#COM;Open Analyss;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY
Requirement:
I need to get the number of users logged in on a particular date.
Eg: from above log ,it should return me that 2 users(user4 and user3 ) were logged In on 2016-02-16 . Requirement is for a batch file.
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=3 delims=; " %%a in (input.txt) do (
set "d=%%a"
set /A "users[!d:-=_!]+=1"
)
echo Users logged in on all dates:
set users
echo/
echo Users logged in on 2016-02-16: %users[2016_02_16]%
Output:
Users logged in on all dates:
users[2016_02_16]=2
users[2016_02_17]=1
users[2016_02_18]=1
Users logged in on 2016-02-16: 2
You may review a detailed explanation of the array method used in this solution at: Arrays, linked lists and other data structures in cmd.exe (batch) script
Method posted by Aacini will work, but the FOR command is rather slow when processing larger amounts of data. If you have very large files and only need to find the number of users on one particular date, I would recommend using the FIND command, which is faster, because the iteration takes place completely within the command.
If you assume that dates only appear within the date data field in the file, you can use FIND /C "date to find" path\filename This will give a single line as output, including the file name and ending with the number of found lines.
If you suspect that dates may occur in other data fields in the file, the following code may be used:
#echo off
SETLOCAL enabledelayedexpansion
SET srcstring=insert your date here
SET file=insert your path and filename here
FOR /F "tokens=3 delims=; " %%F IN ('FIND "%srcstring%" %file%') DO (
IF "%%F"=="%srcstring%" (SET /A "count+=1")
)
echo %count% users found on date %srcstring%
It uses the faster command FIND to find all lines where the date appears, then uses the slower FOR to check that the date appears in the right data field on the line. Since FORonly iterates through those lines that contain the date, it will be significantly faster.
You never state whether there are non-login lines of a different format within the log. I'm going to assume there are.
You also never state what portion of the login line is static. I'm going to assume only the date/time and username change. So this code will only count successful connections. You will have to adjust the code to match your actual conditions.
If all you want to do is print out the count, then you can use FINDSTR with a regular expression to select the relevant rows, and pipe that to FIND to count the rows.
The code below expects the desired date to be passed as a parameter in YYYY-MM-DD format
#echo off
:CountSuccessfulLogins date
set "dt=%~1"
set "prefix= INFO ;servername;"
set "suffix= .*;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY"
findstr /rc:"^%prefix%%dt%%suffix%$" test.log | find /c /v ""
exit /b
If you want the count in a variable, then capture the output with FOR /F
#echo off
:CountSuccessfulLogins date
set "dt=%~1"
set "prefix= INFO ;servername;"
set "suffix= .*;Open Analysis;H5SeLhbEVUKA0ml-kFUw5-151708d6b3Y8Tz;/Metric/core/corePortal;Success;151708fdfgY"
for /f %%N in ('findstr /rc:"^%prefix%%dt%%suffix%$" test.log ^| find /c /v ""') do set cnt=%%N
echo %cnt% Successful Logins on %dt%
exit /b

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.

Windows command prompt hangs for indefinite time

I have a script that performs upgrade to a database.
The script also logs before the upgrade starts, but when this script tries to access the log file it hangs for an indefinte time.
The line that's causing the issue is:
%LOGMESSAGE% Start update %UPDVERSION% .
LOGMESSAGE is a cmd file which is as follow:
SETLOCAL enabledelayedexpansion
SET /A FT=500
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year
/Format:table') DO (
IF NOT !FT!==500 GOTO proceed
SET FD=%%F-%%D-%%A
SET FT=%%B:%%C:%%E
:proceed
SET /A FX="DS"
)
endlocal
The main function of the LOGMESSAGE is to get the current system time.
The log file into which the scripts writes to has no issues and so does the function LOGMESSAGE, as the log file is written many times before the line %LOGMESSAGE% Start update %UPDVERSION% . is called. The script seems to work without any hassle on many other computer, but I am having an issue with one server, the server is running windows server 2003 R2 SP2.
Any idea what the issue might be?
try this:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
SET /A FT=500
FOR /F "tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table^|find "20"') DO (
IF NOT !FT!==500 GOTO proceed
SET FD=%%F-%%D-%%A
SET FT=%%B:%%C:%%E
:proceed
SET /A FX="DS"
)
endlocal
If you just want to get the date and time, you can use
DATE /T
TIME /T
instead of WMI.
Three comments:
.cmd files are rare - normally, .bat files are used. There are minor differences between the two, but I'm not sure whether they would be relevant (I can no longer remember them...)
It's perfectly legitimate to have have a line-break just before the opening single-quote and just after the closing. A break in the middle of the command, I'm not sure about - not saying this IS a problem, but it's so easily eliminated.
I'm no longer sure, since I rarely use XP any more, and never S2003 - but ISTR there were problems with having a label within a block statement. The label seemed to end the block.
So - I'd suggest
running the routine as a .bat instead of a .cmd, using
for...(
'whatever whatever...'
) do (
structure, and implementing whatever tomfoolery is happening about FD, FT and FX within a subroutine.

What does "set _" in a for loop?

I had a problem that Win7 hangs on shutdown screen for over 30 mins.....
then I found this batch file was the cause, but i dont understand what's the purpose of this.
The shutdown only hangs on after join to domain.
This batch file was in c:\ntfs\bin
After I removed this batch file, no more hangs
Issue fixed but i want to know what does this script mean. I dont know much about batch file
please give me a hint
#echo off
for /f "usebackq tokens=1-2 delims==" %%a in (`set _`) do set %%a=
use better:
for /f "delims==" %%a in ('set "_"') do set "%%a="
This code deletes all environment variables starting with _ (underscore) in the current setlocal-endlocal block. If you use this in a batch file without the setlocal command, the varialbles are removed from the current command prompt session.
The use of usebackq and tokens is not needed in this case, see help for for more help on the command prompt.
It deletes all variables that start with an underscore (for example _test or _whatever)

Resources