Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use forfiles to delete a folder and its contents

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?

like image 245
Wally Avatar asked Dec 10 '22 15:12

Wally


1 Answers

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
like image 119
aschipfl Avatar answered Mar 04 '23 03:03

aschipfl