Well that looked like a nice challenge but it is was more tricky than I first imagined.
In broad lines the script works as follows:
- run for 1 specific ESX server. This could be generalised by adding an external loop over all the ESX servers (Get-VMHost)
- find all occurrences of "phd"
- for each occurrence count the number of entries in the parent folder
- if that is 1 then there is only the "phd" directory
- delete the parent directory
Since the DeleteDatastoreFile_Task method requires a Managed Object Reference to a Datacenter when a datastore path is used,
I have written a seperate function that returns the datacenter for a specific ESX server and a specific datastore.
function Get-Datacenter-from-datastore-and-host($dsname,$hostname){
$dcs = Get-Datacenter
foreach($dc in $dcs){
$hs = $dc | Get-VMHost
foreach($h in $hs){
if($h.Name -eq $hostname){
$dss = $h | Get-Datastore
foreach($ds in $dss){
if($ds.Name -eq $dsname){
return $dc
}
}
}
}
}
return $null
}
$hostname = <ESX-hostname>
$searchspecDir = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpecDir.matchpattern = "phd"
$searchspecAll = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
$searchSpecAll.matchpattern = "*"
$esxImpl = Get-VMHost -Name $hostname
$esx = Get-View $esxImpl.ID
$dsBrowser = Get-View $esx.DatastoreBrowser
$fileMgr = Get-View FileManager
foreach($dsImpl in $dsBrowser.Datastore){
$ds = Get-View $dsImpl
if($ds.Summary.Type -eq "VMFS"){
$datastorepath = "[http://" + $ds.Summary.Name + "|http://" + $ds.Summary.Name + "]"
$t1MoRef = $dsBrowser.SearchDatastoreSubFolders_Task($datastorePath, $searchSpecDir)
$t1 = Get-View $t1MoRef
while ($t1.Info.State -eq "running" -or
$t1.Info.State -eq "queued"){$t1 = Get-View $t1MoRef}
foreach ($result in $t1.info.Result){
if($result.FolderPath -ne $datastorepath){
Write-Host $result.FolderPath
$t2MoRef = $dsBrowser.SearchDatastore_Task($result.FolderPath,$searchSpecAll)
$t2 = Get-View $t2MoRef
while ($t2.Info.State -eq "running" -or
$t2.Info.State -eq "queued"){$t2 = Get-View $t1MoRef}
if($t2.Info.Result.File.Count -eq 1){
Write-Host "`t will be deleted"
$tgtdsname = (Get-View -Id $t2.Info.Result.Datastore).Info.Name
$tgthostname = $hostname
$tgtdcImpl = Get-Datacenter-from-datastore-and-host $tgtdsname $tgthostname
if($tgtdcImpl -ne $null){
$tgtdc = Get-View -Id $tgtdcImpl.Id
# $taskMoRef = $fileMgr.DeleteDatastoreFile_Task($result.FolderPath,$tgtdc.MoRef)
$task = Get-View $taskMoRef
while($task.Info.State -eq "running" -or
$task.Info.State -eq "queued"){$task = Get-View $taskMoRef}
}
}
}
}
}
}
Note1: the script only looks for such folders in VMFS datastores.
If other datastore types should be included the "if($ds.Summary.Type -eq "VMFS")" test can be updated or removed.
Note2: the script currently only lists all folders it finds and indicates if it will delete that folder.
If you actually want to delete the folders remove the un-comment the line with the DeleteDatastoreFile_Task statement !