user2644824
user2644824

Reputation: 21

Forfiles command to delete 12 hours old files in .bat file

I know the command to delete the files which are olders then days. How to delete 12 hours old files using forfiles command

I am using forfile command in .bat file

Upvotes: 2

Views: 12283

Answers (2)

dbenham
dbenham

Reputation: 130819

It is ridiculous how difficult it is to work with date and time in Windows batch. I suspect PowerShell may be better, but I don't really know.

I have written a handy hybrid JScript/batch utility that does date and time arithmetic and formatting. It can be used to establish the date and time 12 hours ago, and format it in virtually any format needed. The utility works on any Windows platform from XP onward. It is pure script, so it does not require download or installation of any exe file. getTimestamp.bat is available here. The actual utility is at the bottom of the post, and it includes extensive documentation within the script.

The FOR command can give the last modified date and time, but it uses localized formatting, which makes it difficult to parse with generic code. To make matters worse, it ignores whether daylight savings was in effect or not. So it becomes impossible to accurately determine the elapsed time on days when transitioning either direction between standard time and daylight savings time.

WMIC provides the timestamp, complete with time zone information that accounts for daylight savings, in a universal format that does not vary between locales. The timestamp is in a format that sorts chronologically when doing string comparisons, a very important and useful point.

The getTimestamp.bat utility can be used to get the current timestamp and the cutoff timestamp for deletion. The cutoff needs to be adjusted + or - one hour if the file timestamp and current timestamp do not agree with regard to daylight savings time. The cutoff is formatted to match the WMIC timestamp to make comparisons simple.

Assuming getTimestamp.bat is either in your current folder, or better yet, somewhere in your PATH, then the following should work. I believe it should work anywhere in the world, as long as the local daylight savings adjustment is 1 hour. I don't know if there are any locales where daylight savings is something other than an hour.

I've generally tested the code, but I haven't tested the daylight savings transition days. I might have gotten my logic backwards.

@echo off
setlocal disableDelayedExpansion

:: Define the folder to delete from.
:: The value must be a path without a file name or file wild cards.
set "folderPath=d:\test"

:: Define the hour offset for the deletion cutoff
set /a hourOffset=-12

for /f "delims=" %%F in ("%folderPath%\") do (
  set "driveFilter=%%~dF"
  set "pathFilter=%%~pF"
)
for /f "tokens=1-3" %%A in ('getTimestamp -f "{ums} {zzzz} {z}"') do (
  set "now=%%A"
  set "tz=%%B"
  set "z=%%C"
)
call getTimestamp -d %now% -oh %hourOffset% -f {yyyy}{mm}{dd}{hh}{nn}{ss} -r cutoff
call getTimestamp -d %now% -oh %hourOffset%-1 -f {yyyy}{mm}{dd}{hh}{nn}{ss} -r cutoff-1
call getTimestamp -d %now% -oh %hourOffset%+1 -f {yyyy}{mm}{dd}{hh}{nn}{ss} -r cutoff+1
for /f "tokens=1* delims=." %%A in (
  'wmic datafile where "Drive='%driveFilter%' and Path='%pathFilter:\=\\%'" get LastModified^,Name'
) do for /f "tokens=2* delims=+- " %%C in ("%%B") do (
  if "%%C" neq "%tz:~1%" (
    set "fz=%%B"
    set "file=%%~fD"
    setlocal enableDelayedExpansion
    set /a "fz=!fz:~6,1!1!fz:~7,3!%%1000"
    if !fz! lss !z! if "%%A" leq "%cutoff-1%" del "!file!"
    if !fz! gtr !z! if "%%A" leq "%cutoff+1%" del "!file!"
    endlocal
  ) else (
    if "%%A" leq "%cutoff%" del "%%~fD"
  )
)
exit /b

Upvotes: 2

LS_ᴅᴇᴠ
LS_ᴅᴇᴠ

Reputation: 11151

Ok, I did hard work for you...

SETLOCAL ENABLEDELAYEDEXPANSION
REM 1: Parse date time string
FOR /F "TOKENS=1-5 DELIMS=/-:,. " %%i IN ("%DATE% %TIME%") DO (
    SET year=%%k
    SET month=%%j
    SET day=%%i
    SET hour=%%l
    SET minute=%%m
)
REM 2: Subtract 12 hours, handling day wrap including leap year.
SET /A hour-=12
IF %hour% LSS 0 SET /A hour+=24 & SET /A day-=1
IF %day% LSS 1 (
   SET /A month-=1
   IF !month! LSS 1 SET /A month+=12 & SET /A year-=1
   FOR %%m IN (1 3 5 7 8 10 12) DO IF %%m == !month! SET /A day+=31
   FOR %%m IN (4 6 9 11) DO IF %%m == !month! SET /A day+=30
   IF !month! == 2 (
    SET /A day+=28
    SET /A y4=!year! %% 4
        IF !y4! == 0 (
        SET /A y400=!year! %% 400
        IF !y400! == 0 (
            SET /A day+=1
        ) ELSE (
            SET /A y100=!year! %% 100
            IF NOT !y100! == 0 SET /A day+=1
        )
    )
    )
)
REM 3: Normalize string for later string comparison
CALL :norm_datetime "%day%-%month%-%year% %hour%:%minute%" limit_datetime
REM 4: List file, parse file sate time and delete on comparison verified.
FOR %%f IN (*.*) DO (
    CALL :norm_datetime "%%~tf" file_datetime
    IF !file_datetime! LSS %limit_datetime% ECHO DEL %%f
)
ENDLOCAL
GOTO :EOF

REM 4: function to normalize date time string
REM norm_datetime "time string" output_environment_variable
REM time string format must be d-m-y-h-m[-...], where - is any valid separator.
REM output will be YYYYMMDDTHHMM
:norm_datetime
FOR /F "TOKENS=1-5 DELIMS=/-:,. " %%i IN ("%~1") DO (
    SET year=0000%%k
    SET month=00%%j
    SET day=00%%i
    SET hour=00%%l
    SET minute=00%%m
)
SET %2=%year:~-4%%month:~-2%%day:~-2%T%hour:~-2%%minute:~-2%
GOTO :EOF

Check expected date and time formats in code remarks.

Note that date and time format are system dependent, so this code must be adapted for different systems.

Upvotes: 4

Related Questions