# Batch file to delete folders by date range



## robathomenet (Sep 22, 2010)

I stumbled upon a *closed* thread: http://forums.techguy.org/dos-pda-other/772656-dos-batch-file-delete-folders.html

I wanted to use the batch file that TheOutcaste provided and my [slightly] modified version is below:


```
@Echo Off
:: User Variables
:: Set this to the number of folders you want to keep
Set _NumtoKeep=2
:: Set this to the folder that contains the folders to check and delete
:: Just using the %TMP% dir for safe testing....
Set _Path=%tmp%
If Exist "%temp%\tf}1{" Del "%temp%\tf}1{"
PushD %_Path%
Set _s=%_NumtoKeep%
If %_NumtoKeep%==1 set _s=single
Echo Please wait, searching for folders other than the %_s% most recent
For /F "tokens=* skip=%_NumtoKeep%" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  If Exist "%temp%\tf}1{" (
    Echo %%I:%%~fI >>"%temp%\tf}1{"
    ) Else (
    Echo.>"%temp%\tf}1{"
    Echo Do you wish to delete the following folders?>>"%temp%\tf}1{"
    Echo Date       Name>>"%temp%\tf}1{"
    Echo %%I:%%~fI >>"%temp%\tf}1{"
  ))
PopD
If Not Exist "%temp%\tf}1{" Echo No Folders Found to delete & Goto _Done
Type "%temp%\tf}1{" | More
Set _rdflag= /Q /S
:_Prompt1
Set /P _resp=Delete All, None, or Prompt for each (A/N/P)?
If /I "%_resp:~0,1%"=="N" Goto _Done
If /I "%_resp:~0,1%"=="A" Goto _Removeold
If /I NOT "%_resp:~0,1%"=="P" (Echo (A/N/P only please)&Goto _Prompt1
Set _rdflag=
:_Removeold
For /F "tokens=1* skip=3 Delims=:" %%I In ('type "%temp%\tf}1{"') Do (
 If "%_rdflag%"=="" Echo Deleting
:: rd /s%_rdflag% "%%J")
rd %_rdflag% "%%J")
:_Done
If Exist "%temp%\tf}1{" Del "%temp%\tf}1{"
:: Here for troubleshooting reasons.
pause
```
Now, since I'm looking to schedule this task, I don't need the prompts per se`. But, more importantly, it can't fail when the directory is full. I have a server that has millions of folders/files. It keeps maxing out the HDD with this stuff 'cause the script our dev guys wrote can't delete the older directory. Right now, we have 3 dated directories in here (20100920, 20100921, 20100922). Every day, I have to go in and delete the oldest one by hand... So, today, I'm deleting 20100920...

So, like I said, all I want to do is schedule this batch file to kick off every night and blow away the oldest directory. But, like I said, I can't seem to get this thing to run without throwing errors like the one below:


```
Please wait, searching for folders other than the 2 most recent

Do you wish to delete the following folders?
Date       Name
vmware-user:C:\Users\user\AppData\Local\Temp\vmware-user
CR_1173.tmp:C:\Users\user\AppData\Local\Temp\CR_1173.tmp
moz_mapi:C:\Users\user\AppData\Local\Temp\moz_mapi
TeamViewer:C:\Users\user\AppData\Local\Temp\TeamViewer

Delete All, None, or Prompt for each (A/N/P)?p
Deleting
The directory is not empty.
Deleting
The directory is not empty.
Deleting
The directory is not empty.
Deleting
The directory is not empty.
Press any key to continue . . .
```
Any help would be great...


----------



## TheOutcaste (Aug 8, 2007)

Welcome to TSG!

You changed the rd command and removed the */S* switch. Without that, the RD command will only delete empty folders, not the folders and their contents.

```
:: rd [COLOR=Red][B]/s[/B][/COLOR]%_rdflag% "%%J")
rd %_rdflag% "%%J"
```
If you just want to remove the oldest folder, this will work:

```
@Echo Off
:: User Variables
:: Set this to the folder that contains the folder delete
:: Just using the %TMP% dir for safe testing....
Set _Path=%tmp%
PushD %_Path%
For /F "tokens=*" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
rd /S /Q %_RemoveMe%
PopD
```
Note that on Vista and later, the */AD* switch for the *Dir* command will also list Junction points, which you might not want to delete. In that case use this version instead:

```
@Echo Off
:: User Variables
:: Set this to the folder that contains the folders delete
:: Just using the %TMP% dir for safe testing....
Set _Path=%UserProfile%
PushD %_Path%
For /F "[COLOR=Red][B]tokens=4*[/B][/COLOR]" %%I In ('dir "%_Path%" /AD /O-D /TW^|Findstr /I "<DIR>"') Do Set _RemoveMe=%%J
Echo @rd /S /Q %_RemoveMe%
PopD
```
note that the Tokens=5 line assumes you are using a 12 hour time display. If you use 24 hour, it should be *tokens=3**, or you can add all the code to check The regional settings so you can set that programmatically.
Just check the output of the dir command to see the position of the indicator, it will be column 3 or column 4:

```
09/16/2010  22:59    <DIR>          Documents
09/16/2010  10:59 PM    <DIR>          Documents
```


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> You changed the rd command and removed the */S* switch. Without that, the RD command will only delete empty folders, not the folders and their contents.
> 
> ```
> :: rd [COLOR=Red][B]/s[/B][/COLOR]%_rdflag% "%%J")
> ...


You're right; I did. Sorry but, while testing/troubleshooting, I added it a few lines up - to the variable. I missed the other variable... I'll fix that and test again.... 



TheOutcaste said:


> If you just want to remove the oldest folder, this will work:
> 
> ```
> @Echo Off
> ...


That does seem like a lot less code!! If that's all I really need, I'll have to play with that too...



TheOutcaste said:


> Note that on Vista and later, the */AD* switch for the *Dir* command will also list Junction points, which you might not want to delete. In that case use this version instead:
> 
> ```
> @Echo Off
> ...


Well, it's Server 2008 SP2, so that's the equivalent of Vista. I guess I'll have to remove that switch.



TheOutcaste said:


> note that the Tokens=5 line assumes you are using a 12 hour time display. If you use 24 hour, it should be *tokens=3**, or you can add all the code to check The regional settings so you can set that programmatically.
> Just check the output of the dir command to see the position of the indicator, it will be column 3 or column 4:
> 
> ```
> ...


I don't recall what the server uses for time so I'll have to give that a look and then test some more. I use 24 clocks everywhere but I didn't set up this server....

Thanks for the help! I'll play around and report back.

2010-09-22
1259 EDT


----------



## TheOutcaste (Aug 8, 2007)

Wouldn't expect most user created folders to have Junctions, but better safe than sorry. I'm not sure if RD can actually remove a junction, so that might not be a problem, but if it's the oldest in the list, it won't remove the one you want. Hope that's given you enough info to get it working the way you want.


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> Wouldn't expect most user created folders to have Junctions, but better safe than sorry. I'm not sure if RD can actually remove a junction, so that might not be a problem, but if it's the oldest in the list, it won't remove the one you want. Hope that's given you enough info to get it working the way you want.


For now, I'm going to use the quick and dirty script below:

```
@Echo Off
:: User Variables
:: Set this to the folder that contains the folder delete
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
:: PushD stores a directory or network path in memory so it can be returned to at any time...creating a temporary drive letter.
PushD %_Path%
:: Note that on Vista and later, the /AD switch for the Dir command will also list Junction points, which you might not want to delete.
For /F "tokens=*" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
rd /S /Q %_RemoveMe%
:: PopD changes to the directory or network path stored by the pushd command.
:: If Command Extensions are enabled the POPD command will delete any temporary drive letter created by PUSHD when you POPD that drive off the pushed directory stack.
PopD
```
It looks like it'll work. The only issue will be if the script, which creates the directories daily, ever fails. If it fails to run more than twice, I'll be screwed, as it'll remove the directory needed for that day! I'll have to look into playing with your longer (more involved) script below. FOR loops and IF statements generally screw with me. I've written some pretty nice batch files over the years but there's a lot in your script that I'm either rusty on or was never overly great at understanding. At any rate, thanks for the help thus far. It should save me some time and may even grant me the time needed to study your longer script.


```
@Echo Off
:: User Variables
:: Set this to the number of folders you want to keep
Set _NumtoKeep=2
:: Set this to the folder that contains the folders to check and delete
:: Just using the %TMP% dir for safe testing....
Set _Path=%tmp%
If Exist "%temp%\tf}1{" Del "%temp%\tf}1{"
PushD %_Path%
Set _s=%_NumtoKeep%
If %_NumtoKeep%==1 set _s=single
Echo Please wait, searching for folders other than the %_s% most recent
For /F "tokens=* skip=%_NumtoKeep%" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  If Exist "%temp%\tf}1{" (
    Echo %%I:%%~fI >>"%temp%\tf}1{"
    ) Else (
    Echo.>"%temp%\tf}1{"
    Echo Do you wish to delete the following folders?>>"%temp%\tf}1{"
    Echo Date       Name>>"%temp%\tf}1{"
    Echo %%I:%%~fI >>"%temp%\tf}1{"
  ))
PopD
If Not Exist "%temp%\tf}1{" Echo No Folders Found to delete & Goto _Done
Type "%temp%\tf}1{" | More
Set _rdflag= /q
:_Prompt1
Set /P _resp=Delete All, None, or Prompt for each (A/N/P)?
If /I "%_resp:~0,1%"=="N" Goto _Done
If /I "%_resp:~0,1%"=="A" Goto _Removeold
If /I NOT "%_resp:~0,1%"=="P" (Echo (A/N/P only please)&Goto _Prompt1
Set _rdflag=
:_Removeold
For /F "tokens=1* skip=3 Delims=:" %%I In ('type "%temp%\tf}1{"') Do (
 If "%_rdflag%"=="" Echo Deleting
 rd /s%_rdflag% "%%J")
:_Done
If Exist "%temp%\tf}1{" Del "%temp%\tf}1{"
:: PAUSE is here for troubleshooting reasons.
pause
```


----------



## TheOutcaste (Aug 8, 2007)

You can add a skip parameter to keep the X newest folders:

```
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
```
Easy with the /B (bare format, as there is no header, and the *.* and *..* entries are not included).
Another option is to count the number of directories found, and only delete if it's more than a minimum

```
Set _Count=0
For /F "tokens=*" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
Set _RemoveMe=%%I
Set /A _Count+=1
)
If %_Count% LEQ 2 Goto :Error
```


----------



## Squashman (Apr 4, 2003)

skip=2


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> You can add a skip parameter to keep the X newest folders:
> 
> ```
> For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
> ...


Yeah, I think I like the *skip=2* option.... I'll add that to make the script a little more "safe."


----------



## TheOutcaste (Aug 8, 2007)

Couple more points to avoid an error if _Removeme doesn't get defined, and to make sure it doesn't use a previous value


```
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
If Defined _RemoveMe rd /S /Q %_RemoveMe%
```


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> Couple more points to avoid an error if _Removeme doesn't get defined, and to make sure it doesn't use a previous value
> 
> 
> ```
> ...


Understood. I'll play with that as well.


----------



## Squashman (Apr 4, 2003)

robathomenet said:


> Understood. I'll play with that as well.


Don't play with it too much. You may go blind!


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> Couple more points to avoid an error if _Removeme doesn't get defined, and to make sure it doesn't use a previous value
> 
> 
> ```
> ...


Couldn't you also use *SETLOCAL/ENDLOCAL* to prevent this as well?


----------



## TheOutcaste (Aug 8, 2007)

For this use the variable shouldn't have a previous value. That would only be a concern if it was used someplace else, or you ran the program from the command prompt more than once and didn't close the window to clear the variables.
SetLocal/EndLocal would prevent that.

SetLocal only affects variables defined/changed _after_ the SetLocal command is used. If the variable is defined before you run the batch file, and the For loop does not set a value, the rd statement will use that previous value.

Just good practice to clear the variable first, just in case. You may copy this section to another file at a later date and not think if it at that time.

That's also why I used _RemoveMe for the variable instead of FolderName or FileName or something generic. Hopefully less likely someone will assign a name of something they want to keep to a variable named _RemoveMe.

The check to see if the variable was defined is only needed to prevent the display of this error: *The syntax of the command is incorrect.*

The program will continue, so it's only cosmetic. When running as a task the window would close before you could read it


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> For this use the variable shouldn't have a previous value. That would only be a concern if it was used someplace else, or you ran the program from the command prompt more than once and didn't close the window to clear the variables.
> SetLocal/EndLocal would prevent that.
> 
> SetLocal only affects variables defined/changed _after_ the SetLocal command is used. If the variable is defined before you run the batch file, and the For loop does not set a value, the rd statement will use that previous value.
> ...


Gotcha... I've always had *SETLOCAL* high up in my batch files and then one of the last lines would have the *ENDLOCAL* statement. The only thing I'd ever have to worry about was the batch file failing and never reaching the *ENDLOCAL* part of the batch file. To help catch theses errors, I'd always use *IF %ERRORLEVEL%* statements... Either way, clearing that variable seems like a good idea was well...


----------



## robathomenet (Sep 22, 2010)

I just checked the directory to see how it was doing. It looks like it's cleaning the directory but doing too good a job! 

There's only 1 directory in there and the script was to leave 2 in there at all times. Did I do something wrong?


```
@Echo Off
:: Got help with this here: http://techguy.org/951662
:: User Variables
:: Set this to the folder that contains the folder delete
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
:: PushD stores a directory or network path in memory so it can be returned to at any time...creating a temporary drive letter.
PushD %_Path%
:: Note that on Vista and later, the /AD switch for the Dir command will also list Junction points, which you might not want to delete.
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
If defined _RemoveMe rd /S /Q %_RemoveMe%
:: PopD changes to the directory or network path stored by the pushd command.
:: If Command Extensions are enabled the POPD command will delete any temporary drive letter created by PUSHD when you POPD that drive off the pushed directory stack.
PopD
```


----------



## TheOutcaste (Aug 8, 2007)

Opps, I was throwing out pieces of code instead of the whole thing.
The above should skip the two newest folders, but will only delete the one oldest, as the rd command is not part of the loop.


```
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  Set _RemoveMe=%%I
  If defined _RemoveMe rd /S /Q %_RemoveMe%
)
```
Are you sure there are no junction points in the folder?
Run this first to see what the difference is:

```
@Echo Off
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
PushD %_Path%
Echo All Folders
Echo.
For /F "tokens=*" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Echo %%I
Echo.
Echo Skip first two folders
Echo.
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Echo %%I
PopD
```
If you remove the /B switch you'll see if any of those are Junction points


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> Opps, I was throwing out pieces of code instead of the whole thing.
> The above should skip the two newest folders, but will only delete the one oldest, as the rd command is not part of the loop.
> 
> 
> ...


Okay, running:

```
@Echo Off
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
PushD %_Path%
Echo All Folders
Echo.
For /F "tokens=*" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Echo %%I
Echo.
Echo Skip first two folders
Echo.
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Echo %%I
PopD
pause
```
Gave me: 

```
All Folders

20100928

Skip first two folders

Press any key to continue . . .
```
Running:

```
@Echo Off
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
PushD %_Path%
Echo All Folders
Echo.
::For /F "tokens=*" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Echo %%I
For /F "tokens=*" %%I In ('dir "%_Path%" /AD /O-D /TW') Do Echo %%I
Echo.
Echo Skip first two folders
Echo.
::For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Echo %%I
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /O-D /TW') Do Echo %%I
PopD
pause
```
Gave me: 

```
All Folders

Volume in drive E is RAID10
Volume Serial Number is DC35-EB7D
Directory of E:\Applications\Cars_com_Photos\www\DMI_DP
09/28/2010  12:53 PM    <DIR>          20100928
09/28/2010  07:52 AM    <DIR>          ..
09/28/2010  07:52 AM    <DIR>          .
0 File(s)              0 bytes
3 Dir(s)  258,479,312,896 bytes free

Skip first two folders

Directory of E:\Applications\Cars_com_Photos\www\DMI_DP
09/28/2010  12:53 PM    <DIR>          20100928
09/28/2010  07:52 AM    <DIR>          ..
09/28/2010  07:52 AM    <DIR>          .
0 File(s)              0 bytes
3 Dir(s)  258,479,312,896 bytes free
Press any key to continue . . .
```
Neither of them looked much different. Meaning, they only found the one directory.

I've also tweaked my original script from:

```
@Echo Off
:: Got help with this here: http://techguy.org/951662
:: User Variables
:: Set this to the folder that contains the folder delete
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
:: PushD stores a directory or network path in memory so it can be returned to at any time...creating a temporary drive letter.
PushD %_Path%
:: Note that on Vista and later, the /AD switch for the Dir command will also list Junction points, which you might not want to delete.
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
If defined _RemoveMe rd /S /Q %_RemoveMe%
:: PopD changes to the directory or network path stored by the pushd command.
:: If Command Extensions are enabled the POPD command will delete any temporary drive letter created by PUSHD when you POPD that drive off the pushed directory stack.
PopD
```
to:

```
@Echo Off
:: Got help with this here: http://techguy.org/951662
:: User Variables
:: Set this to the folder that contains the folder delete
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
:: PushD stores a directory or network path in memory so it can be returned to at any time...creating a temporary drive letter.
PushD %_Path%
:: Note that on Vista and later, the /AD switch for the Dir command will also list Junction points, which you might not want to delete.
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  Set _RemoveMe=%%I
  If defined _RemoveMe rd /S /Q %_RemoveMe%
)
:: PopD changes to the directory or network path stored by the pushd command.
:: If Command Extensions are enabled the POPD command will delete any temporary drive letter created by PUSHD when you POPD that drive off the pushed directory stack.
PopD
```


----------



## TheOutcaste (Aug 8, 2007)

Well it's certainly skipping the one folder.
You could create two test folders, then see if it only lists the oldest one (20100928) in the skip two loop. Don't run the delete program, or it will delete today's folder though.

I don't see any reason why it wouldn't leave two folders in there, even the original should have left at least two, in fact it would only have removed one folder when run (the oldest) as long as there are three or more folders present.


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> Well it's certainly skipping the one folder.
> You could create two test folders, then see if it only lists the oldest one (20100928) in the skip two loop. Don't run the delete program, or it will delete today's folder though.
> 
> I don't see any reason why it wouldn't leave two folders in there, even the original should have left at least two, in fact it would only have removed one folder when run (the oldest) as long as there are three or more folders present.


I'll play around and see what happens. What's the worst that could happen anyway - delete millions of files and hundreds of thousands folders with production data???


----------



## robathomenet (Sep 22, 2010)

I had an issue today. The script is fine, as near as I can tell, but it's throwing an error.

*Current Script:*

```
:: @Echo Off
:: Got help with this here: http://techguy.org/951662
:: User Variables
:: Set this to the folder that contains the folder delete
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
:: PushD stores a directory or network path in memory so it can be returned to at any time...creating a temporary drive letter.
PushD %_Path%
:: Note that on Vista and later, the /AD switch for the Dir command will also list Junction points, which you might not want to delete.
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  Set _RemoveMe=%%I
  If defined _RemoveMe rmdir /S /Q %_RemoveMe%
)
:: PopD changes to the directory or network path stored by the pushd command.
:: If Command Extensions are enabled the POPD command will delete any temporary drive letter created by PUSHD when you POPD that drive off the pushed directory stack.
PopD
pause
```
*Error:*

```
C:\>Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP

C:\>PushD E:\Applications\Cars_com_Photos\www\DMI_DP

E:\Applications\Cars_com_Photos\www\DMI_DP>Set _RemoveMe=

E:\Applications\Cars_com_Photos\www\DMI_DP>For /F "tokens=* skip=2" %I In ('dir
"E:\Applications\Cars_com_Photos\www\DMI_DP" /AD /B /O-D /TW') Do (
Set _RemoveMe=%I
 If defined _RemoveMe rmdir /S /Q
)

E:\Applications\Cars_com_Photos\www\DMI_DP>(
Set _RemoveMe=20101006
 If defined _RemoveMe rmdir /S /Q
)
The syntax of the command is incorrect.

E:\Applications\Cars_com_Photos\www\DMI_DP>PopD

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


----------



## robathomenet (Sep 22, 2010)

Quick note: I've noticed that when I run the command manually, I see strange errors.


```
U:\>rmdir /q /s E:\Applications\Cars_com_Photos\www\DMI_DP\20101005
E:\Applications\Cars_com_Photos\www\DMI_DP\20101005\DP26798\1J4RR4GG7BC519050_6_of_9.jpg - Access is denied.
E:\Applications\Cars_com_Photos\www\DMI_DP\20101005\DP26798\1J4RR4GG7BC519050_7_of_9.jpg - The system cannot find the file specified.
E:\Applications\Cars_com_Photos\www\DMI_DP\20101005\DP26798\1J4RR4GG7BC519050_8_of_9.jpg - The system cannot find the file specified.
E:\Applications\Cars_com_Photos\www\DMI_DP\20101005\DP26798\1J4RR4GG7BC519050_9_of_9.jpg - The system cannot find the file specified.
```
There may be data corruption so I'll have to watch it. It's worked fine all the time so I doubt it's the script!


----------



## TheOutcaste (Aug 8, 2007)

You've added parentheses and included the RmDir command inside the loop. Missed that in your previous post:
Original:

```
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do Set _RemoveMe=%%I
If defined _RemoveMe rd /S /Q %_RemoveMe%
```
Modified:

```
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do [COLOR=Red][B]([/B][/COLOR]
  Set _RemoveMe=%%I
  If defined _RemoveMe rmdir /S /Q %_RemoveMe%
[COLOR=Red][B])[/B][/COLOR]
```
That puts the *If Defined* statement on the same line as the *For* and *Set* statements.
To use the current value of a variable on the same line as it is set or changed, you have to use Delayed Expansion.
This also means it will delete *all* but the two newest folders, not just the one oldest folder.
If that's what you want, to remove all but the two newest, add this line as line 2:
*SetLocal EnableDelayedExpansion*
And change the *If Defined* line to this:
*If Defined _RemoveMe rmdir /S /Q !_RemoveMe!*
Probably be a good idea to add quotes around the variable in case you change the folder structure and have a folder name that includes a space.
*If Defined _RemoveMe rmdir /S /Q "!_RemoveMe!"*

If you only want to delete the one oldest folder on each run, move the *If Defined* line so it's after the parenthesis:

```
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do [COLOR=Red][B]([/B][/COLOR]
  Set _RemoveMe=%%I
[COLOR=Red][B])[/B][/COLOR]
If Defined _RemoveMe rmdir /S /Q "%_RemoveMe%"
```
Some ideas on the errors when running manually:
The *Access is Denied* error could occur if the file is in use.
The *The system cannot find the file specified.* error can happen if some other process deleted, moved, or renamed the file before the RD command got to that file. Rmdir generates a list of files first, then starts deleting them, so there is time for other processes to delete files.


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> You've added parentheses and included the RmDir command inside the loop. Missed that in your previous post:
> Original:
> 
> ```
> ...


It ran fine last night and I didn't make any changes.... 

All I need it to do is *delete everything but the 2 newest directories. *The current script has been modified [this morning] as follows:


```
@Echo Off
SetLocal EnableDelayedExpansion
:: Got help with this here: http://techguy.org/951662
:: User Variables
:: Set this to the folder that contains the folder to delete
Set _Path=E:\Applications\Cars_com_Photos\www\DMI_DP
:: PushD stores a directory or network path in memory so it can be returned to at any time...creating a temporary drive letter.
PushD %_Path%
:: Note that on Vista and later, the /AD switch for the Dir command will also list Junction points, which you might not want to delete.
Set _RemoveMe=
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  Set _RemoveMe=%%I
  If defined _RemoveMe rmdir /S /Q "!%_RemoveMe%!"
)
:: PopD changes to the directory or network path stored by the pushd command.
:: If Command Extensions are enabled the POPD command will delete any temporary drive letter created by PUSHD when you POPD that drive off the pushed directory stack.
PopD
:: pause
```
Curious though... What's with the "!" before and after the variable? Never seen/used that before. Then I again, I've never used SetLocal EnableDelayedExpansion before either so maybe that has something to do with it...


----------



## TheOutcaste (Aug 8, 2007)

You need to replace the *%* with the *!*, not use them both.
*If defined _RemoveMe rmdir /S /Q "!_RemoveMe!"*

When Delayed Expansion is enabled, the *!* tells the command processor to delay expansion until the line is executed, the *%* means use normal expansion, meaning replace the variable with it's value when the Line is read.
This is all one line as far as the command processor is concerned, even though it's seen as 4 lines in an editor:

```
For /F "tokens=* skip=2" %%I In ('dir "%_Path%" /AD /B /O-D /TW') Do (
  Set _RemoveMe=%%I
  If defined _RemoveMe rmdir /S /Q "!%_RemoveMe%!"
)
```
See the help for *Set* (type *Set /?* in a Command Prompt) for more info


----------



## robathomenet (Sep 22, 2010)

TheOutcaste said:


> You need to replace the *%* with the *!*, not use them both.
> *If defined _RemoveMe rmdir /S /Q "!_RemoveMe!"*


Sorry, I missed that....  It's fixed now. We'll see what it does.


----------



## srhoades (May 15, 2003)

I use this program to manage my image backups (The older versions of acronis just plain don't work at managing them, although they are supposed to)

http://cyber-d.blogspot.com/2005/10/cyber-ds-auto-delete-101.html


----------



## robathomenet (Sep 22, 2010)

Before this script, I was using Erase Temp with command switches and it worked but it seemed slower than this batch file...


----------

