Page 1 of 1

Alert if files found in a folder are older than X hours

Posted: 03 Jan 2011 22:54
by JohnDoe
I really liked tips for date and time but I wanted to know if its possible to write a script that can be run to monitor a folder and to generate an alert if files found in the folder are older than X amount of hours rather than amount of days in one of the examples given.

Re: Alert if files found in a folder are older than X hours

Posted: 04 Jan 2011 19:00
by aGerman
Working with DateTime values is terrible in batch. There are no native functions for calculating.
The main problem is that you will find difficult sequences and separators. Ex:
04.01.2010
Tue 01/04/2010
2010-01-04

etc.
I always try to equalize it by reading the "international" settings in the registry (but without guarantee).
If you would like defining a maximum age of hours then you should use minutes for the comparision. The reason why is that batch doesn't know floating point values. 1.9999 is 1 inside a batch environment.

How ever. Try something like that:

Code: Select all

@echo off &setlocal

REM folder to be checked
set "Folder=C:\path\to\your\folder"

REM accepted maximum age in minutes
set "MaxAge=60"

REM try to change the working directory
pushd "%Folder%" ||goto :eof

REM read international registry settings
call :GetInternationalSettings DateOrder DateSeparator TimeSeparator

REM get the current number of elapsed minutes since Jan. 1st 1970, 00:00
call :GetNumberOfMinutes %DateOrder% "%DateSeparator%" "%TimeSeparator%" "%date%" "%time%" CurrentMinutes

REM check all files
for /f "delims=" %%a in ('dir /a-d /b') do (
  set "filename=%%a                                        "
  setlocal enabledelayedexpansion
  call :GetNumberOfMinutes %DateOrder% "%DateSeparator%" "%TimeSeparator%" %%~ta FileMinutes
  set /a age = CurrentMinutes - FileMinutes
  if !age! gtr %MaxAge% (
    set /a age /= 60
    echo !filename:~,40! -^> older than !age! hours
  )
  endlocal
)

popd

pause
goto :eof

:GetInternationalSettings
setlocal
for /f "tokens=3" %%a in ('reg query "HKCU\Control Panel\International" /v iDate') do set "iDate=%%a"
for /f "tokens=3" %%a in ('reg query "HKCU\Control Panel\International" /v sDate') do set "sDate=%%a"
for /f "tokens=3" %%a in ('reg query "HKCU\Control Panel\International" /v sTime') do set "sTime=%%a"
endlocal &set "%~1=%iDate%" &set "%~2=%sDate%" &set "%~3=%sTime%"
goto :eof


:GetNumberOfMinutes
setlocal
set "iDate=%~1" &set "sDate=%~2" &set "sTime=%~3" &set "strDate=%~4" &set "strTime=%~5"
for /f "tokens=2" %%i in ("%strDate%") do set "strDate=%%i"
for /f "tokens=1-4 delims=%sDate%" %%a in ("%strDate%") do (
  if %iDate%==0 set /a mm=100%%a %% 100,dd=100%%b %% 100,yy=10000%%c %% 10000
  if %iDate%==1 set /a dd=100%%a %% 100,mm=100%%b %% 100,yy=10000%%c %% 10000
  if %iDate%==2 set /a yy=10000%%a %% 10000,mm=100%%b %% 100,dd=100%%c %% 100
)
for /f "tokens=1,2 delims=%sTime% " %%a in ("%strTime%") do set /a hh=100%%a %% 100, nn=100%%b %% 100
set /a z=(14-mm)/12,y=yy+4800-z,x=mm+12*z-3,d=153*x+2,d=d/5+dd+y*365+y/4-y/100+y/400-2472633, n=d*1440+hh*60+nn
endlocal &set "%~6=%n%"
goto :eof


Regards
aGerman

Re: Alert if files found in a folder are older than X hours

Posted: 05 Jan 2011 01:18
by JohnDoe
Not sure what happen to my last reply but here it is again

Thank you for looking at this agerman (after getting a copy of reg.exe from winxp on to this win2k machine the following error came up)


C:\Alert>monitor2
Invalid number. Numeric constants are either decimal (17),
hexadecimal (0x11), or octal (021).
STEST.XML -> older than 17559704 hours


I think this is where it broke due to get a A in the time stamp

C:\Alert\Monitor>(
set "filename=STEST.XML "
setlocal enabledelayedexpansion
call :GetNumberOfMinutes 0 "/" ":" 10/24/07 10:43a FileMinutes
set /a age = CurrentMinutes - FileMinutes
if !age! GTR 60 (
set /a age /= 60
echo !filename:~,40! -> older than !age! hours
)
endlocal
)



As this gives us

set /a hh=10010 % 100, nn=10043a % 100


and this is the cause of the above error


Code: Select all

C:\Alert>REM @echo off &setlocal 

C:\Alert>REM folder to be checked

C:\Alert>set "Folder=C:\Alert\Monitor\"

C:\Alert>REM accepted maximum age in minutes

C:\Alert>set "MaxAge=60"

C:\Alert>REM try to change the working directory

C:\Alert>pushd "C:\Alert\Monitor\"   || goto :eof

C:\Alert\Monitor>REM read international registry settings

C:\Alert\Monitor>call :GetInternationalSettings DateOrder DateSeparator TimeSeparator

C:\Alert\Monitor>setlocal

C:\Alert\Monitor>for /F "tokens=3" %a in ('reg query "HKCU\Control Panel\International" /v iDate') do set "iDate=%a"

C:\Alert\Monitor>set "iDate=VERSION"

C:\Alert\Monitor>set "iDate=0"

C:\Alert\Monitor>for /F "tokens=3" %a in ('reg query "HKCU\Control Panel\International" /v sDate') do set "sDate=%a"

C:\Alert\Monitor>set "sDate=VERSION"

C:\Alert\Monitor>set "sDate=/"

C:\Alert\Monitor>for /F "tokens=3" %a in ('reg query "HKCU\Control Panel\International" /v sTime') do set "sTime=%a"

C:\Alert\Monitor>set "sTime=VERSION"

C:\Alert\Monitor>set "sTime=:"

C:\Alert\Monitor>endlocal   & set "DateOrder=0"   & set "DateSeparator=/"   & set "TimeSeparator=:"

C:\Alert\Monitor>goto :eof

C:\Alert\Monitor>REM get the current number of elapsed minutes since Jan. 1st 1970, 00:00

C:\Alert\Monitor>call :GetNumberOfMinutes 0 "/" ":" "Wed 01/05/2011" "18:09:21.94" CurrentMinutes

C:\Alert\Monitor>setlocal

C:\Alert\Monitor>set "iDate=0"   & set "sDate=/"   & set "sTime=:"   & set "strDate=Wed 01/05/2011"   & set "strTime=18:09:21.94"

C:\Alert\Monitor>for /F "tokens=2" %i in ("Wed 01/05/2011") do set "strDate=%i"

C:\Alert\Monitor>set "strDate=01/05/2011"

C:\Alert\Monitor>for /F "tokens=1-4 delims=/" %a in ("01/05/2011") do (
if 0 == 0 set /a mm=100%a % 100,dd=100%b % 100,yy=10000%c % 10000 
 if 0 == 1 set /a dd=100%a % 100,mm=100%b % 100,yy=10000%c % 10000 
 if 0 == 2 set /a yy=10000%a % 10000,mm=100%b % 100,dd=100%c % 100
)

C:\Alert\Monitor>(
if 0 == 0 set /a mm=10001 % 100,dd=10005 % 100,yy=100002011 % 10000 
 if 0 == 1 set /a dd=10001 % 100,mm=10005 % 100,yy=100002011 % 10000 
 if 0 == 2 set /a yy=1000001 % 10000,mm=10005 % 100,dd=1002011 % 100
)

C:\Alert\Monitor>for /F "tokens=1,2 delims=: " %a in ("18:09:21.94") do set /a hh=100%a % 100, nn=100%b % 100

C:\Alert\Monitor>set /a hh=10018 % 100, nn=10009 % 100

C:\Alert\Monitor>set /a z=(14-mm)/12,y=yy+4800-z,x=mm+12*z-3,d=153*x+2,d=d/5+dd+y*365+y/4-y/100+y/400-2472633, n=d*1440+hh*60+nn

C:\Alert\Monitor>endlocal   & set "CurrentMinutes=21570849"

C:\Alert\Monitor>goto :eof

C:\Alert\Monitor>REM check all files

C:\Alert\Monitor>for /F "delims=" %a in ('dir /a-d /b') do (
set "filename=%a                                        " 
 setlocal enabledelayedexpansion 
 call :GetNumberOfMinutes 0 "/" ":" %~ta FileMinutes 
 set /a age = CurrentMinutes - FileMinutes 
 if !age! GTR 60 (
set /a age /= 60 
 echo !filename:~,40! -> older than !age! hours

 endlocal
)

C:\Alert\Monitor>(
set "filename=STEST.XML                                        " 
 setlocal enabledelayedexpansion 
 call :GetNumberOfMinutes 0 "/" ":" 10/24/07 10:43a FileMinutes 
 set /a age = CurrentMinutes - FileMinutes 
 if !age! GTR 60 (
set /a age /= 60 
 echo !filename:~,40! -> older than !age! hours

 endlocal
)

C:\Alert\Monitor>setlocal

C:\Alert\Monitor>set "iDate=0"   & set "sDate=/"   & set "sTime=:"   & set "strDate=10/24/07"   & set "strTime=10:43a"

C:\Alert\Monitor>for /F "tokens=2" %i in ("10/24/07") do set "strDate=%i"

C:\Alert\Monitor>for /F "tokens=1-4 delims=/" %a in ("10/24/07") do (
if 0 == 0 set /a mm=100%a % 100,dd=100%b % 100,yy=10000%c % 10000 
 if 0 == 1 set /a dd=100%a % 100,mm=100%b % 100,yy=10000%c % 10000 
 if 0 == 2 set /a yy=10000%a % 10000,mm=100%b % 100,dd=100%c % 100
)

C:\Alert\Monitor>(
if 0 == 0 set /a mm=10010 % 100,dd=10024 % 100,yy=1000007 % 10000 
 if 0 == 1 set /a dd=10010 % 100,mm=10024 % 100,yy=1000007 % 10000 
 if 0 == 2 set /a yy=1000010 % 10000,mm=10024 % 100,dd=10007 % 100
)

C:\Alert\Monitor>for /F "tokens=1,2 delims=: " %a in ("10:43a") do set /a hh=100%a % 100, nn=100%b % 100

C:\Alert\Monitor>set /a hh=10010 % 100, nn=10043a % 100

C:\Alert\Monitor>set /a z=(14-mm)/12,y=yy+4800-z,x=mm+12*z-3,d=153*x+2,d=d/5+dd+y*365+y/4-y/100+y/400-2472633, n=d*1440+hh*60+nn

C:\Alert\Monitor>endlocal   & set "FileMinutes=-1032011400"

C:\Alert\Monitor>goto :eof
STEST.XML                                -> older than 17559704 hours

C:\Alert\Monitor>popd

C:\Alert>pause
Press any key to continue . . .

C:\Alert>goto :eof

Re: Alert if files found in a folder are older than X hours

Posted: 05 Jan 2011 05:16
by aGerman
I see. While the time in variable %time% comes in 24h format, the time of the FOR loop comes in 12h format and the "a" is for "a.m.".
Could you confirm?

Regards
aGerman

Edit:
Try if this works right.

Code: Select all

@echo off &setlocal

REM folder to be checked
set "Folder=C:\Alert\Monitor"

REM accepted maximum age in minutes
set "MaxAge=60"

pushd "%Folder%" ||goto :eof
call :GetInternationalSettings DateOrder DateSeparator TimeSeparator
call :GetNumberOfMinutes %DateOrder% "%DateSeparator%" "%TimeSeparator%" "%date%" "%time%" CurrentMinutes
for /f "delims=" %%a in ('dir /a-d /b') do (
  set "filename=%%a                                        "
  setlocal enabledelayedexpansion
  call :GetNumberOfMinutes %DateOrder% "%DateSeparator%" "%TimeSeparator%" %%~ta FileMinutes
  set /a age=CurrentMinutes - FileMinutes
  if !age! gtr %MaxAge% (
    set /a age/=60
    echo !filename:~,40! -^> older than !age! hours
  )
  endlocal
)
popd
pause
goto :eof

:GetInternationalSettings
setlocal
for /f "tokens=3" %%a in ('reg query "HKCU\Control Panel\International" /v iDate') do set "iDate=%%a"
for /f "tokens=3" %%a in ('reg query "HKCU\Control Panel\International" /v sDate') do set "sDate=%%a"
for /f "tokens=3" %%a in ('reg query "HKCU\Control Panel\International" /v sTime') do set "sTime=%%a"
endlocal &set "%~1=%iDate%" &set "%~2=%sDate%" &set "%~3=%sTime%"
goto :eof

:GetNumberOfMinutes
setlocal
set "iDate=%~1" &set "sDate=%~2" &set "sTime=%~3" &set "strDate=%~4" &set "strTime=%~5"
for /f "tokens=2" %%i in ("%strDate%") do set "strDate=%%i"
for /f "tokens=1-4 delims=%sDate%" %%a in ("%strDate%") do (
  if %iDate%==0 set /a mm=100%%a %% 100,dd=100%%b %% 100,yy=10000%%c %% 10000
  if %iDate%==1 set /a dd=100%%a %% 100,mm=100%%b %% 100,yy=10000%%c %% 10000
  if %iDate%==2 set /a yy=10000%%a %% 10000,mm=100%%b %% 100,dd=100%%c %% 100
)
for /f "tokens=1,2 delims=%sTime% " %%a in ("%strTime%") do (set /a hh=100%%a %% 100 &set "nn=%%b")
if "%nn:~-1%" equ "p" if "%hh%" neq "12" set /a hh+=12
if "%nn:~-1%" equ "a" if "%hh%" equ "12" set /a hh=0
for /f "delims=ap" %%a in ("%nn%") do set /a nn=100%%a %% 100
set /a z=(14-mm)/12,y=yy+4800-z,x=mm+12*z-3,d=153*x+2,d=d/5+dd+y*365+y/4-y/100+y/400-2472633,n=d*1440+hh*60+nn
endlocal &set "%~6=%n%"
goto :eof


Re: Alert if files found in a folder are older than X hours

Posted: 05 Jan 2011 19:59
by JohnDoe
Thanks for the help aGerman, yes its funny that the files have a or p on them. I think this is a feature of windows 2000 on windows 7 it shows as either AM or PM

The code runs but not sure as expected

Here is the file listing

Code: Select all

 Directory of C:\Alert\Monitor

01/06/2011  12:41p                   0 file1.txt
10/24/2007  10:43a                 514 file2.txt


And the result from the batch file

Code: Select all

C:\Alert>monitortest.bat
file1.txt                                -> older than 17531640 hours
file2.txt                                -> older than 17559722 hours
Press any key to continue . . .

Re: Alert if files found in a folder are older than X hours

Posted: 05 Jan 2011 21:04
by ghostmachine4
JohnDoe wrote:I really liked tips for date and time but I wanted to know if its possible to write a script that can be run to monitor a folder and to generate an alert if files found in the folder are older than X amount of hours rather than amount of days in one of the examples given.

download findutils for windows, then use this one liner to find files older than 1 hr ago

Code: Select all

c:\test> gnu_find.exe c:\directory -type f  -mmin +60 


if there are output displayed, then you can do the alert.
Its certainly easier than to maintain a whole bunch of inefficient DOS batch commands that mess around with registry. Alternatively, if you can't download stuff, using vbscript is still better than batch, since it can do Date maths pretty easily.

Re: Alert if files found in a folder are older than X hours

Posted: 06 Jan 2011 11:43
by aGerman
I'm at my wits end. It's like I wrote in my first post: "Working with DateTime values is terrible in batch."
I agree with ghostmachine4.

Regards
aGerman

Re: Alert if files found in a folder are older than X hours

Posted: 06 Jan 2011 13:55
by JohnDoe
aGerman i completely agree about times in windows there always seems to be not set standard of how time stamps are shown.

ghostmachine4 thanks for the link I will download and have a play with it.

Re: Alert if files found in a folder are older than X hours

Posted: 11 Jan 2011 23:07
by JohnDoe
Well this is what I have so far please let me know what you think.

I could not get any error levels from the gnu find so I had to pump the output to findstr

Code: Select all

@echo off &setlocal
gnu_find C:\Alert\Monitor -type f -mmin +60 | findstr "txt" >nul && goto foundfiles
echo. All is good go back to sleep
goto exit

:foundfiles
echo. Alert ! Alert! we found files
:exit


ghostmachine4 Is there any way with gnu_find to find files with a certain extension, as well as not to search sub folders ?

Re: Alert if files found in a folder are older than X hours

Posted: 12 Jan 2011 22:07
by JohnDoe
Ok here is the near final code.

We have an application that picks up files from a certain folder, every now and again a file will come in corrupt as such it will block the application and it will not pickup any of the other files.

I hope to have created this workaround script to check for files in the folder and if they are older than a hour then it will move and rename the oldest file in hope of finding the corrupt file and alert the helpdesk.

Please let me know what you think I am sure there might be some better ways of doing some of these things

Code: Select all

@echo off &setlocal
cls

REM folder to be checked
set "CheckFolder=C:\Alert\Monitor"
set "MoveFolder=C:\Alert\bad"
set "MaxAge=60"

REM Find and check for any files that might be suck in the inbound message folder.
gnu_find %CheckFolder% -maxdepth 1 -type f -name *TCLMD* -mmin +%MaxAge% | findstr ".mq" >nul && goto FindOldest
echo.&echo.&echo.
echo.       No Files found over %MaxAge% minutes so we can go back to sleep
wait 5
goto Exit

:FindOldest
Rem Find the oldest file as this file might be a corrupt message and the reason for the router failing to pickup these messages.
for /f "tokens=*" %%D in ('dir %CheckFolder%\*.MQ /A-D /B /O-D') do set OldestMsg=%%D

echo.&echo.&echo.
echo       The oldest message found in %CheckFolder% is %OldestMsg%
echo.

Rem Generate a random number based on the date so we can use it to rename the file.
for /f "tokens=2-8 delims=/:. " %%A in ("%date%:%time: =0%") do set "UNIQUE=%%C%%A%%B%%D%%E%%F%%G"

Rem Lets rename and move the file so it is not picked up again and allow the router to move on and we hope pickup the other messages.

echo.&echo.&echo.
echo       Moving %CheckFolder%\%OldestMsg% to  %MoveFolder%\%UNIQUE%.badsms
      move "%CheckFolder%\%OldestMsg%" %MoveFolder%\%UNIQUE%.badsms   
echo.
goto :SendAlert


Rem We had better let the Helpdesk know.
:SendAlert
ECHO.
ECHO Sending an Alert to let the Helpdesk know
ECHO.

set AlertTime=%Time:~0,5% %Date:~4,6%%Date:~-2%

sendemail -s 127.0.0.1:25 -o message-header="X-Priority: 1" -f  italert@domain.com -t helpdesk@domain.com -u "There Appears to be a stuck message on %computername%" at %Time:~0,5% -m "Warning a message on %computername% was blocking the inbound router. It generated this alarm at %AlertTime% "\n""\n" A copy of the offending message has been attached to this message. Please take a look at the file most messages fail due to a Alpha from field or a funny character in the body of the message. "\n""\n" If you want to try and process the message again copy '%MoveFolder%\%UNIQUE%.badsms' into %Foldercheck%" -a "%MoveFolder%\%UNIQUE%.badsms"

echo.
echo Alert Sent we are all done Time to Zzzzzzzzz.

Rem Clean up environment space

set "CheckFolder="
set "MoveFolder="
set "MaxAge="
set "OldestMsg="
set "UNIQUE="
set "AlertTime="
wait 5
goto Exit