• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 399
  • Last Modified:

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?
0
annexit
Asked:
annexit
  • 5
  • 5
1 Solution
 
Bill PrewCommented:
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
0
 
annexitAuthor Commented:
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.  :)
0
 
Bill PrewCommented:
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
0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
annexitAuthor Commented:
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.
0
 
becraigCommented:
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
0
 
annexitAuthor Commented:
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.
0
 
Bill PrewCommented:
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
0
 
annexitAuthor Commented:
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
0
 
Bill PrewCommented:
Here is a little bit of editing on the command line parm, and a few comments added.  Should be good to go now.

@echo off
setlocal EnableDelayedExpansion

REM Make sure a parm was entered on the command line
if "%~1" EQU "" (
  echo Usage: %~nx0 [root-folder]
  exit /b 
)

REM Make sure the folder name ends in "\", and that it exists
set BaseDir=%~1
if "%BaseDir:~-1%" NEQ "\" set BaseDir=%BaseDir%\
if not exist "%BaseDir%" (
  echo *ERROR* Specified folder does not exist!
  exit /b
)

REM Define list of extension that prevent deletion of the folder
set Exceptions=vhd,vhdx

REM Get each folder under the root folder
for /d %%D in ("%BaseDir%*.*") do (

  REM See if there are any exception files anywhere underneath this folder
  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
    )
  )

  REM If no exception found, remove this folder
  if !Count! EQU 0 (
    echo Deleting folder "%%~D"
    ECHO rd /s /q "%%~D"
  )

)

Open in new window

~bp
0
 
annexitAuthor Commented:
Awesome, I'll give it a shot.  Thanks again!  :)
0
 
Bill PrewCommented:
Welcome.

~bp
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now