Windows – Delete all files older than 365 days, but exclude certain folders

batch filewindows-server-2003

Edit: After @Mbu answer I realized that my first approach with leading numbers in folders as criteria to exclude isn't the right way. I decided to use a fixed list of folders to exclude.


I want to delete certain files via batch , but exclude a given set of paths to be checked

Example structure

E:.
|───MyBatchFile.cmd
|
├───yes
│   │   no.doc        | file has wrong extension
│   │   yes.cfg
│   │   yes.dat
│   │   yes.hgr
│   │
│   └───yes
│           yes.cfg
│           yes.dat
│           yes.hgr
│
├───yes
│       yes.cfg
│       no.dat        | file is too new, modified within a year
│       no.hgr        | file is too new, modified within a year
│
|───no1               | folder is on blacklist
|       importantstuff
│
└───no2               | folder is on blacklist
        importantstuff

The yes and no file names demonstrate which files should be deleted

What I want

Search all files in all folders and subfolders starting at the folder where the batch is placed. If all following conditions are true, delete the file

  1. file extension is .cfg, .dat, .hgr or .txt
  2. modified time is more than 365 days old
  3. Path is not on blacklist

What I have tried

Based on this question, I have:

@echo off
for %%i in (.cfg, .dat, .hdr, .txt) do (
  forfiles /s /m *%%i /d -365 /c "cmd /c del @path"
)
pause

Two of three issues are solved, but how do I exclude a given set of folders.
Like E:\no1 and E:\no2 from my example.

Best Answer

You can try this script but it will work only if %%~tA in your regional settings is returning the file date using YMD format. If not, the comparison will not work as expected.

@Echo Off
setlocal enabledelayedexpansion

for /r %%A in (*.cfg;*.dat;*.hdr) do (
  set p=%%~pA
  set numeric=no
  if "!p:~1,1!"=="0" set numeric=yes
  if "!p:~1,1!"=="1" set numeric=yes
  if "!p:~1,1!"=="2" set numeric=yes
  if "!p:~1,1!"=="3" set numeric=yes
  if "!p:~1,1!"=="4" set numeric=yes
  if "!p:~1,1!"=="5" set numeric=yes
  if "!p:~1,1!"=="6" set numeric=yes
  if "!p:~1,1!"=="7" set numeric=yes
  if "!p:~1,1!"=="8" set numeric=yes
  if "!p:~1,1!"=="9" set numeric=yes

  if !numeric!==yes (
    if "%%~tA" LSS "2012-11-08" (
      del %%A
    )
  )
)

endlocal

EDIT

I think I have managed to modify the script to work the way you want. I had to get rid of /r switch and call a subroutine recursively or the blacklist would not work properly. The blacklist should be stored in blacklist.txt file in the same directory where the script resides. The file should contain full paths to excluded folders without quotes:

D:\excluded folder1
D:\excluded folder2
D:\included folder\excluded folder3

For each folder that is not blacklisted a subroutine is called which searches for files based on extension and then each file's date is compared with the date given. Please test the script thoroughly. I am afraid it may break on folder names containing special characters like % or ^.

@Echo Off
call :browse D:
goto :EOF

:browse
for /d %%A in ("%~1\*") do (
  find /i "%%A" %~dp0blacklist.txt > nul
  if errorlevel 1 (
    call :delete "%%A"
    call :browse "%%A"
  ) else (
    echo SKIP %%A
  )
)
goto :EOF

:delete
for %%A in ("%~1\*.cfg" "%~1\*.dat" "%~1\*.hdr") do (
  if "%%~tA" LSS "2012-10-08" (
    echo DEL  %%A
    del "%%A"
  ) else (
    echo SAVE %%A
  )
)
goto :EOF
Related Question