4

I am attempting to purge a public directory, so when an item is older than 30 days it should be deleted. I have a batch file setup with the following command:

forfiles /p "C:\PATH\USERS\PATH\" /s /m *.* /c "cmd /c Del @path /q" /d -30

This works great. However, the issue is, that it only deletes the items within the folders within the path.

Example: C:\PATH\USERS\PATH\HelloWorld\file.text is over 30 days old. But the command only deletes file.text, not the folder.

Would I have to check to see if the folder is empty and then delete the folder with another command?

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Wally
  • 57
  • 1
  • 1
  • 10
  • 2
    use [rd](http://ss64.com/nt/rd.html) to remove a folder. It won't remove an non-emty folder, unless you give it a `/s /q` – Stephan Sep 07 '16 at 19:14
  • Are you wanting to check if the folder is 30 days old? If so, then use the `@isdir` variable to check directories only and then delete the directory. – Squashman Sep 07 '16 at 19:37

2 Answers2

15

The command line you are using is quite dangerous (I just copied it here and reordered the switches):

forfiles /S /D -30 /P "C:\PATH\USERS\PATH\" /M "*.*" /C "cmd /C del /Q @path"

Because forfilesreturns both files and directories. Supposing there is a directory called container that matches the search criteria (last modified 30 days ago or earlier), the executed del command line is del "C:\PATH\USERS\PATH\container" /Q, which deletes all files in there, even those not fulfilling the search criteria (note that del \folder behaves like del \folder\*).

To solve this issue, you need to filter for file or directories, like this:

forfiles /S /D -30 /P "C:\PATH\USERS\PATH" /M "*" /C "cmd /C if @isdir==FALSE del @path"

I also changed the file mask from *.* to *, because forfiles, opposed to all internal commands, does not match files with no extension in case *.* is given. In addition I removed the trailing \ from the path, because otherwise, forfiles raises an error: ERROR: The directory name is invalid..


But now for something completely different -- the answer to your actual question:

Since forfiles /S will return a directory before it returns its sub-items, it does not make sense do check whether the directory is empty or not in the same command line, you need to do that later.

For that purpose, you can either use a second forfiles loop like this (also checking their last modification dates, if you like; otherwise, remove the /D -30 portion):

forfiles /S /D -30 /P "C:\PATH\USERS\PATH" /M "*" /C "cmd /C if @isdir==TRUE rd @path 2> nul"

Or alternatively, if the directory modification dates are not relevant, you can use a for /D loop, which is also faster:

for /D %%I in ("C:\PATH\USERS\PATH\*") do rd "%%~fI" 2> nul
aschipfl
  • 33,626
  • 12
  • 54
  • 99
0

for cmd

for /D %I in ("%cd%\*") do rd "%~fI" 2> nul

for bat file

for /D %%I in ("%cd%\*") do rd "%%~fI" 2> nul
Itchydon
  • 2,572
  • 6
  • 19
  • 33