# DOS Batch File to Delete Certain Folders Based on Name



## JadeMonkeyStang (Jan 10, 2012)

I'm trying to figure out how to write a batch file (which will be part of a logon script) in Windows XP which will delete certain user profile directories in C:\Documents and Settings.

What I need is to leave any directories which start with certain letters (A/a and Y/y) and delete those which start with any other character. I'm sure this is relatively simple and probably only requires a FOR loop with the RMDIR /S command or a couple of nested for loops with DEL. What I'm not sure is how to setup the loop, step through the directories in C:\Documents and Settings, or skip over files starting with certain letters.

I've done some basic batch file and scripting work but haven't messed with anything looping or manipulating variables. Any help or suggestions would be much appreciated.

Thanks!


----------



## Squashman (Apr 4, 2003)

And you don't have any computers with Vista or Windows 7 that will be using this login script?


----------



## JadeMonkeyStang (Jan 10, 2012)

No, everything is WinXP at the moment with no plans for an upgrade for at least the next year.


----------



## Squashman (Apr 4, 2003)

Remove the *echo* before the *rmdir* when you feel comfortable with the output. Then it will remove the directories.

```
@echo off
pushd "C:\Documents and Settings\"
for /F "tokens=*" %%I in ('dir /a:d-s-h /b ^| findstr /B /I /V /C:"a" /C:"y"') do echo rmdir /q /s "%%I"
popd
```


----------



## JadeMonkeyStang (Jan 10, 2012)

Thanks! The script works great.


To check my understanding:
@echo off
:Turns off text output of commands to monitor.

pushd "C:\Documents and Settings\"
:Sets working directory.

for /F "tokens=*" %%I 
:Creates FOR loop, /F allows us to create our own delimiter.
:Tokens=* indicates that we want to look at all of the tokens created, since we did not specifiy a delimiter and each token will be the directory/folder name we want to look at.
:%%I is the token/variable we'll use to track the directory name.

in ('dir /a:d-s-h /b ^
:Looks for results that are Directories, not System Files, and not Hidden Files. Uses bare formatting and sets starting position to the begining of each line.

| findstr /B /I /V /C:"a" /C:"y"')
:On the set of results from the search above, finds a string at the begining of a line, which is not case sensitive, and returns strings which do not match, using literal strings of "a" and "y".

do echo 
:Executes the below command on everything returned from the search above.

rmdir /q /s "%%I"
:Will delete directories quietly and removes all files, subfolders, and the directory itself.

popd
:Returns to the directory specified previously by pushd.



Does that sound about right?


----------



## Squashman (Apr 4, 2003)

You pretty much got it. You have to be the first person I have ever seen break down code that they have been given. I am pleasantly surprised by this. Most people won't bother to understand the code.

You need the /F option in the FOR loop in order to execute those commands inside the parenthesis and the commands need to be surrounded by Single Quotes. Otherwise it will see what is inside the () as a literal string to parse.

You could also setup the FOR options like this.
FOR /F "Delims=" %%I in......
And to be really super anal
FOR /F "tokens=* delims=" %%I in.......

You will need to remove the ECHO if you want the directories deleted. Right now all it is doing is telling you that it will remove those directories.

If you ever move to Vista or Windows 7 this can easily be changed to something like this

IF EXIST "C:\Documents and Settings\" pushd "C:\Documents and Settings\"
IF EXIST "C:\Users\" pushd "C:\Users\" pushd "C:\Users\"

In theory you should not have both but you could also look at the output of the VER command to determine if the script is executing on XP or Vista or 7 and then do the appropriate PUSHD command.


----------



## JadeMonkeyStang (Jan 10, 2012)

Squashman said:


> You pretty much got it. You have to be the first person I have ever seen break down code that they have been given. I am pleasantly surprised by this. Most people won't bother to understand the code..


I'll take that as a compliment. ;-) I'm trying to understand things as best I can as I'm sure there are much more powerful things I'll be able to use this for in the future.



Squashman said:


> You will need to remove the ECHO if you want the directories deleted. Right now all it is doing is telling you that it will remove those directories.
> .


I understand that part, I am used to using echo from my very limited scripting experience. I actually meant to remove the echo from my reply.



Squashman said:


> If you ever move to Vista or Windows 7 this can easily be changed to something like this
> 
> IF EXIST "C:\Documents and Settings\" pushd "C:\Documents and Settings\"
> IF EXIST "C:\Users\" pushd "C:\Users\" pushd "C:\Users\"
> ...


The above applies to the begining of the script correct? Would I still use the same FOR loop in a Vista or 7 environment?


----------



## Squashman (Apr 4, 2003)

Same for loop. Just giving you options to set the working directory when you change to Windows 7.


----------



## JadeMonkeyStang (Jan 10, 2012)

I just got some more information and need to add some functionality to this script. Apparently we do not want to run it as a logon/logoff script but instead want to use it while we have users logged in. This means that I need to be able to detect which user that is logged on and not delete their profile folder. 

Most of our user accounts begin with a letter followed by numbers but some are alphabetical only so I will need to be able to handle either type. I'm hoping there is a way to grab the name of the currently logged on user. Then we should just need to add an IF statement in the loop to make sure we don't RMDIR on the current user's profile.


----------



## Squashman (Apr 4, 2003)

Are you aware of all the environmental variables?

Open up a CMD prompt and type: *set*
I think you will find a variable in there that will very useful to you.


----------



## JadeMonkeyStang (Jan 10, 2012)

Sweet. That was much easier than I thought it would be. I did not know about the set command or about the pre-definied environmental variables. When I first ran the set command a saw what was returned I thought I was going to have to parse the results to extract the information I wanted, then I did a little more research and figured out I only had to put the name I wanted with % on each side. Perfect.

Here is my finished (for the moment) code:


```
@echo off
pushd "C:\Documents and Settings\"
for /F "tokens=*" %%I in ('dir /a:d-s-h /b ^| findstr /B /I /V /C:%username% /C:"a" /C:"b" /C:"f" /C:"y"') do echo rmdir /q /s "%%I"
popd
```
It's amazing how much effort it can take to write 4 little lines.

Thanks a ton for the help Squashman, hopefully this will last at least a day until someone wants something else changed. Beers are on me.


----------



## Squashman (Apr 4, 2003)

You could of course run into this situation which will kill your users directory.
I work in a domain environment and if you look at these two variables you will definitely see a problem

```
USERNAME=Squash
USERPROFILE=C:\Documents and Settings\Squash.NA
```
The NA is the domain I am in. So if your code runs on my computer you would kill my directory on my PC. Not that I keep that much stuff on my PC. I actually save everything to my network drive or a 2nd HD I have mounted inside the computer.


----------



## JadeMonkeyStang (Jan 10, 2012)

Squashman said:


> You could of course run into this situation which will kill your users directory.
> I work in a domain environment and if you look at these two variables you will definitely see a problem
> 
> ```
> ...


Hmm, are you sure? We are in a domain environment as well and I tested this as corrupt profiles result in a situation where users have multiple profile folders (which is the reason for the script) that take the form:
C:\Documents and Settings\User1
C:\Documents and Settings\User1.abc
C:\Documents and Settings\User1.abc.001
C:\Documents and Settings\User1.abc.002
and so on...

I created similar folders on my machine and when I test ran the script it would not delete any of those folders if User1 was logged in and I had /C:%username% included in the findstr statement. This seems to be the same behavior that results in /C:"a" excluding any usernames which start with the letter a.

The opposite would of course not be true, if your username was User1.abc then
C:\Documents and Settings\User1 would get deleted.


----------



## Squashman (Apr 4, 2003)

You are right. It is not doing an exact match. I am sick today. Please forgive my drug induced judgment!


----------



## JadeMonkeyStang (Jan 10, 2012)

No worries at all, you brought up a good point and it made me go back again and double check that it was doing exactly what I intended.

If I wanted it to only save the most recent profile, is that an easy change or one that requires a great deal more work? I'm assuming since the folders are sorted in order itcould run through them with the for loop and once it matched the username, check the next folder. If that matched the same user then it would delete the previous folder, if it did not it would move on as you had reached that user's last profile folder. Make sense

It would also be possible to use one for loop to count the number of folders a user had and then delete n-1 of their folders.

Is there a better way?


----------



## Squashman (Apr 4, 2003)

If a user has multiple profiles you could nest in another for loop and use the DIR command to sort the directory list by the newest folder first. In the 2nd For loop you would use a skip=1 as an option which would leave the newest directory out there.

```
@echo off
pushd "C:\Documents and Settings\"
for /F "tokens=*" %%I in ('dir /a:d-s-h /b ^| findstr /B /I /V /C:%username% /C:"a" /C:"b" /C:"f" /C:"y"') do (
	for /F "skip=1 tokens=*" %%F in ('dir "%%I*" /a:d-s-h /b /O-D') do (
		echo rmdir /q /s "%%F"
	)
)
popd
```


----------

