Link to home
Start Free TrialLog in
Avatar of annexit
annexitFlag for United States of America

asked on

Batch file to delete folders that don't contain a certain file type

Greetings Experts!

I'm in need of a batch file that will delete folder trees that don't contain a particular file type, in this case a VHD or VHDX file.  Another way to say it is a batch file that deletes all folder trees but skips folder trees that have a VHD or VHDX file in them.

Some examples:

d:\folder1\folder2\filename.vhd
     = "folder1" folder and all it's contents are skipped/untouched

d:\folder1\filename.vhd
     = "folder1" folder and all it's contents are skipped/untouched

d:\folder1\folder2\filename.vhd
     = "folder1" folder and all it's contents are skipped/untouched

d:\folder1\folder2\folder3\filename.vhdx
     = "folder1" folder and all it's contents are skipped/untouched

d:\folder1\folder2\filename.vhdx
     = "folder1" folder and all it's contents are skipped/untouched

d:\folder1\filename.vhdx
     = "folder1" folder and all it's contents are skipped/untouched

d:\folder1\bogus.txt
     = "folder1" folder and all it's contents are DELETED

d:\folder1\folder2\bogus.txt
     = "folder1" folder and all it's contents are DELETED

d:\folder1\folder2\folder3\bogus.txt
     = "folder1" folder and all it's contents are DELETED

The script needs to take a command line argument for the target root directory.  Example:
     cleanup.bat d:\    (this would jibe with the above examples)

Lastly, when a folder is deleted that info is dumped into a log file (filename.log) so I can see what was deleted.

I inherited a VB script that does this but it's not working 100% and as I'm not a VB guy I'd rather use batch which I'm more familiar with.

Thoughts?
Avatar of Bill Prew
Bill Prew

So, anytime a vhd or vhdx file exists, all parent folders of it are untouched, right?

What about this case, should the folder3 be removed, and the foled1 and folder2 left?

d:\folder1\folder2\filename.vhd
d:\folder1\folder3\filename.txt

~bp
Avatar of annexit

ASKER

In that case "folder1" should be skipped.

The parent folder "folder1" should be totally skipped if a VHD or VHDX file is present anywhere inside it.  

Whatever else in in "folder1" doesn't matter - if there's a VHD or VHDX file anywhere inside it the entire "folder1" is skipped.

Hopefully that clears things up.  :)
Okay, seems a little odd, but it's your script :-).

So this "rule" applies to all the first level folders under the root folder passed on the command line, but NOT the root folder itself, right?  Meaning if there are vhd files under d:\folder1, but none under d:\folder2 then we go ahead and remove d:\folder2?

Sorry for the questions, it's my process, I like to fully understand the need before working up a script.

~bp
Avatar of annexit

ASKER

I welcome questions so no worries there.  :)

It may make more sense if I give the background for this.  I've got multiple Hyper-V hosts running here and there's a glitch in Hyper-V where sometimes deleting a virtual machine doesn't actually delete the config or snapshot files that were part of it, only the VHD or VHDX file (the VM's hard disk file).

So on my hosts I have this folder structure:
D:\HOSTNAME\Virtual Machines\VIRTUALMACHINENAME

I need the script to look at all of the "VIRTUALMACHINENAME" folders inside of "Virtual Machines" and if there is no VHD or VHDX file present anywhere inside it delete the "VIRTUALMACHINENAME" folder.

If there is a VHD or VHDX file anywhere inside of the "VIRTUALMACHINENAME" folder than the entire "VIRTUALMACHINENAME" folder is skipped and left untouched.

The reason for the deletion is because without a VHD or VHDX file the "VIRTUALMACHINENAME" folder is orphaned and should have already been deleted.
Something like this should work in PowerShell:

$folder1 = "C:\F1"
$folder2 = "C:\F2"
$folder3 = "C:\F3"
$folders = ($folder1, $folder2, $folder3) 
#you can replace the above and feed in from a text file
foreach ($folder in $folders) 
{
if (gci -path $folder -recurse | where {$_.extension -eq ".vhd"})
{write-host "$folder should NOT be deleted" -fore green }
else 
{Remove-Item -path $folder -recurse -Force  }
}

Open in new window



You can use whatif to test
Avatar of annexit

ASKER

Hmm... I'd rather use batch but I know some PowerShell so that would be doable.

What if I don't know the "VIRTUALMACHINENAME" folder names?  They're always different as they are deployed and deleted by end users without my interaction.

I would only be able to point the script to the root target:
     D:\HOSTNAME\Virtual Machines
as that never changes.

After that the script would have to look at all of the D:\HOSTNAME\Virtual Machines\VIRTUALMACHINENAME folders on its own and do the VHD/VHDX check.
Here's a BAT script that should do it.  We should do a little more editing, but out of time for a bit, wanted to get you this.  It has the RD commented out right now with an ECHO for testing, so you can see what it would remove without actually deleting anything.  

@echo off
setlocal EnableDelayedExpansion

set BaseDir=%~1
set Exceptions=vhd,vhdx

for /d %%D in ("%BaseDir%\*.*") do (
  set Count=0
  for %%X in (%Exceptions%) do (
    for /f %%C in ('dir /b /a-d /s "%%~D\*.%%~X" 2^>NUL ^| find /v /c ""') do (
      set /a Count+=%%C
    )
  )
  if !Count! EQU 0 (
    echo Deleting folder "%%~D"
    ECHO rd /s /q "%%~D"
  )
)

Open in new window

~bp
Avatar of annexit

ASKER

I did some testing and that seems to work well.  Let me know if you think of any tweaks, otherwise I'd say we can close this one out.  Thank you!  :D
ASKER CERTIFIED SOLUTION
Avatar of Bill Prew
Bill Prew

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of annexit

ASKER

Awesome, I'll give it a shot.  Thanks again!  :)
Welcome.

~bp