views:

382

answers:

3

I'm trial and erroring a trivial batch script:

I need to execute the .bat and have it iterate through all the files in the current directory and delete all files (and subfolders) except for itself and two other files.

This works:

@echo off
for /f %%f in ('dir /b c:\d\test') do (del %%f)

This doesn't:

@echo off
for /f %%f in ('dir /b c:\d\test') do (if (true) (del %%f))

Why? (in place of "if (true)" I'd like to say "if not filename=='foo' or filename=='bar'" etc)

Many thank you's

EDIT: @rangerchris, perfect, thanks. now how to include folders and subfolderrs in the iteration?

A: 

From the command line, it works okay here with:

for %i in (*) do if not "%i" == "startgd.bat" echo %i

Obviously, change %i to %%i in a .bat file though. What error (if any) are you getting? Maybe you just need to use the quotes correctly (double quotes rather than single?)

EDIT: For ignoring two files, this works:

for %i in (*) do if not "%i" == "startgd.bat" if not "%i" == "msdelog.log" echo %i

EDIT 2 [based on @Pong's edit to make this complete]: To recurse down folders, just pass the /s switch to dir. So you'll have something like:

for /f %i in ('dir /s /b c:\') do if not "%i" == "C:\startgd.bat" if not "%i" == "c:\path\to\other\file" echo %i
Chris J
@Pong -- answer edited. If this doesn't work, can you give more details on what this doesn't do that you're trying to achieve? Either way, this should give the ground tools needed to give a solution.
Chris J
The folders need to be deleted, not just the files within them
Pong
I don't think there's anyway to determine whether an item is a file or directory from a batch script. You could try doing something based on rmdir (rmdir /s will delete all files and associated subfolders), having taken a backup of the two files you want to keep first so you can restore once done. So: copy /some/path/file1 /backup/file1 ... copy /some/other/path/file2 ... /backup/file2 ... rmdir /q /s /some ... mkdir /some/other/path ... then copy files back over.
Chris J
Actually ... there might be a way - but only in two passes. The first (above) deletes files, then modify to do 'dir /s /b /ad' instead (gets only directories) and change the del to an rmdir.
Chris J
A: 

This should work:

for /f %%f in ('dir /b c:\d\test') do (if '%%f' == 'foo' del %%f)

Basically, you need to quote the variable in your conditional test.

ars
A: 

Pong, in this code, fill the "Keep" variable with the needed filenames.

I took for granted that those files cound be anywhere so in the test I really check the name+extension only, not the path, so they could be inany sub-path.

EDIT: Ok, there goes the revised more deeply tested version for Pong. Sorry for posting too hastily, wanted to help but guess I didn't test my script enough.

Although this time, allows me to show an example or recursive programming (function :CleanDirs calling itself) in XP batch programming :)

Cleanup.cmd:

@echo off
set Keep="%~nx0" "file1.ext" "file2.ext"
set StartDir=%~dp0
call :CleanDirs "%StartDir:~0,-1%"
exit /b 0
:CleanDirs
    call :CleanFiles "%~1"
    for /f "delims=" %%d in ('dir /ad /b "%~1"2^>nul') do call :CleanDirs "%~1\%%~d"
    if exist "%~1" rmdir /Q "%~1">nul 2>nul
    exit /b 0
:CleanFiles
    for /f "delims=" %%f in ('dir /a-d /b "%~1"2^>nul') do (
     set _keep=
     for %%k in (%Keep%) do if /i "%%~nxf"=="%%~k" set _keep=yes
     if not defined _keep del /f "%~1\%%~f" 2>nul
    )
    exit /b 0

Still, hope this helps even more.

Notes

set Keep= : Adjust with any filename you need to keep. The script will keep the subfolders holding those files.

set StartDir=%~dp0 : Will ajust itself to whereever the script is located. If you want to move the script elsewhere, you could call it with a directory name as argument and change assignation here as ="%~1"

Coding tips

%~1 : (Tild) remove enclosing quotes. Will not remove ALL quotes, only one leading/Trailing.

%~nx0 : (tild n x)gets the file**n**ame+e**x**t of the batchfile. Warning, this will change if this is put into a function. Adjust as needed.

%~dp0 : (tild d p) Gets the drive/full path (including trailing baskslash (\) of the batchfile. Warning, this will change if this is put into a function. Adjust as needed.

%StartDir:~0,-1% : (Tild Start,Stop) Gets a substring of the variable, here from position 0 to last character minus one position (used to strip trailing \).

Jay
this looks promising but it doesn't work. executing the above script (without modification) should delete everything except file1.ext and file2.ext right? well, it deletes nothing. curious.
Pong
Ok I see what's wrong, will correct the code.
Jay
Jay, this deletes only empty folders. Maybe one last edit? Otherwise it works great - thank you!!
Pong
i changed "rmdir" to "del" -- bad result :)
Pong
Hey you were right -- in my testing tree I did create dummy third-level dir, but didn't put files in this one, to test deleting of empty directories lol. We should be good now!
Jay
Hey glad you liked it!
Jay