build 7bbbddf7 | content blog-content@c8490fa · 338 posts | profiles 20 · corpus 267 | 0 skipped | | format
apiVersion: soultec.ch/v1kind: Postmetadata: name: powercli-find-zombie-files-on-datastores locale: de labels: author: dario-doerflinger series: scripting capability/automation: 1.78 vendor/vmware: 0.88 annotations: source: blog-content/posts/de/powercli-find-zombie-files-on-datastores.md route: /de/insights/powercli-find-zombie-files-on-datastores/ schema: /nerd/schema/posts.json markdown: /de/insights/powercli-find-zombie-files-on-datastores.mdspec: title: Zombie-Dateien auf Datastores finden date: 2017-07-25 author: dario-doerflinger locale: de summary: >- RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert. capabilities: [automation] vendors: [vmware] series: scripting migrated: 2026-08-24 comments: 7 noticeKind: superseded noticeText: >- RVTools und das vCenter melden verwaiste Dateien inzwischen direkt, dieses Script braucht es auf aktuellen Versionen also nicht mehr. Es bleibt hier, weil das Vorgehen erklärt, was der Report eigentlich tut. translationReviewed: false draft: false sections: - body: | RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert. Ohne würde ich meine Arbeit nicht machen wollen. Ein Kunde wollte einen Mail-Report über die «Zombie»-Dateien auf seinen Datastores. Nach einem RVTools-Check hatte er gesehen, dass viel Platz für Snapshot-Delta-Disks draufging, die seine Backup-Lösung nicht entfernt hatte. Dieses Problem sehen wir in fast jeder Umgebung. Also haben wir ein Script gebaut, das die Dateien meldet, die zu keiner laufenden VM gehören. Bei einer grossen Umgebung braucht das Script lange, hab also Geduld. Danke an Luc aus der PowerCLI Community, der uns geholfen hat, die Funktion etwas schneller zu machen. (http://www.lucd.info/2016/09/13/orphaned-files-revisited/) Update: Dieses Script liegt inzwischen auf [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts). - heading:

Das Script

body: | ```powershell ################################################################################## # Script: RmOrphanedFiles.ps1 # Datum: 25.07.2017 # Version: 2.1 # History: Added Comments # Replaced Add-PSSnapin with Module Command # Replaced Get-VmwOrphan Function ################################################################################## [CmdletBinding(SupportsShouldProcess=$true)] Param( [parameter()] [String]$vCenter = "virtualfrogvc.virtual.frog", # Change to a SMTP server in your environment [string]$SmtpHost = "mail.virtual.frog", # Change to default email address you want emails to be coming from [string]$From = "[email protected]", # Change to default email address you would like to receive emails [Array]$To = @("[email protected]","[email protected]"), # Change to default Report Filename you like [string]$Attachment = "$env:temp\OrphanedFileReport-"+(Get-Date -f "yyyy-MM-dd")+".csv" ) function Get-VmwOrphan{ <# .EXAMPLE PS> Get-VmwOrphaned -Datastore DS1 .EXAMPLE PS> Get-Datastore -Name DS* | Get-VmwOrphaned #> [CmdletBinding()] param( [parameter(Mandatory=$true,ValueFromPipeline=$true)] [PSObject[]]$Datastore ) Begin{ $flags = New-Object VMware.Vim.FileQueryFlags $flags.FileOwner = $true $flags.FileSize = $true $flags.FileType = $true $flags.Modification = $true $qFloppy = New-Object VMware.Vim.FloppyImageFileQuery $qFolder = New-Object VMware.Vim.FolderFileQuery $qISO = New-Object VMware.Vim.IsoImageFileQuery $qConfig = New-Object VMware.Vim.VmConfigFileQuery $qConfig.Details = New-Object VMware.Vim.VmConfigFileQueryFlags $qConfig.Details.ConfigVersion = $true $qTemplate = New-Object VMware.Vim.TemplateConfigFileQuery $qTemplate.Details = New-Object VMware.Vim.VmConfigFileQueryFlags $qTemplate.Details.ConfigVersion = $true $qDisk = New-Object VMware.Vim.VmDiskFileQuery $qDisk.Details = New-Object VMware.Vim.VmDiskFileQueryFlags $qDisk.Details.CapacityKB = $true $qDisk.Details.DiskExtents = $true $qDisk.Details.DiskType = $true $qDisk.Details.HardwareVersion = $true $qDisk.Details.Thin = $true $qLog = New-Object VMware.Vim.VmLogFileQuery $qRAM = New-Object VMware.Vim.VmNvramFileQuery $qSnap = New-Object VMware.Vim.VmSnapshotFileQuery $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec $searchSpec.details = $flags $searchSpec.Query = $qFloppy,$qFolder,$qISO,$qConfig,$qTemplate,$qDisk,$qLog,$qRAM,$qSnap $searchSpec.sortFoldersFirst = $true } Process{ foreach($ds in $Datastore){ if($ds.GetType().Name -eq "String"){ $ds = Get-Datastore -Name $ds Write-Host "Checking Datastore $ds" } # Only shared VMFS datastore if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){ Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tLooking at $($ds.Name)" # Define file DB $fileTab = @{} # Get datastore files $dsBrowser = Get-View -Id $ds.ExtensionData.browser $rootPath = "[" + $ds.Name + "]" $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) | Sort-Object -Property {$_.FolderPath.Length} foreach($folder in $searchResult){ foreach ($file in $folder.File){ $key = "$($folder.FolderPath)$(if($folder.FolderPath[-1] -eq ']'){' '})$($file.Path)" $fileTab.Add($key,$file) $folderKey = "$($folder.FolderPath.TrimEnd('/'))" if($fileTab.ContainsKey($folderKey)){ $fileTab.Remove($folderKey) } } } # Get VM inventory Get-VM -Datastore $ds | %{ $_.ExtensionData.LayoutEx.File | %{ if($fileTab.ContainsKey($_.Name)){ $fileTab.Remove($_.Name) } } } # Get Template inventory Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{ $_.ExtensionData.LayoutEx.File | %{ if($fileTab.ContainsKey($_.Name)){ $fileTab.Remove($_.Name) } } } # Remove system files & folders from list $systemFiles = $fileTab.Keys | where{$_ -match "] \.|vmkdump"} $systemFiles | %{ $fileTab.Remove($_) } # Organise remaining files if($fileTab.Count){ $fileTab.GetEnumerator() | %{ $obj = [ordered]@{ Name = $_.Value.Path Folder = $_.Name Size = $_.Value.FileSize CapacityKB = $_.Value.CapacityKb Modification = $_.Value.Modification Owner = $_.Value.Owner Thin = $_.Value.Thin Extents = $_.Value.DiskExtents -join ',' DiskType = $_.Value.DiskType HWVersion = $_.Value.HardwareVersion } New-Object PSObject -Property $obj } Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tFound orphaned files on $($ds.Name)!" } else{ Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tNo orphaned files found on $($ds.Name)." } } } } } Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null Connect-VIServer $vCenter -WarningAction SilentlyContinue | Out-Null Write-Host "Connected to $vCenter. Starting script" $bodyh = (Get-Date -f "yyyy-MM-dd HH:mm:ss") + " - the following orphaned files were found on Datastores. `n" $body = Get-Datastore | Get-VmwOrphan $body | Export-Csv "$Attachment" -NoTypeInformation -UseCulture $body = $bodyh + ($body | Out-String) $subject = "Report - orphaned Files on Datastores for $vCenter" send-mailmessage -from "$from" -to $to -subject "$subject" -body "$body" -Attachment "$Attachment" -smtpServer $SmtpHost Disconnect-VIServer -Server $vCenter -Force:$true -Confirm:$false ```status: corpus: 267 alsoLike: - {ref: posts/vmware-explore-las-vegas-hackathon-2025, score: 1.00} - {ref: posts/vmware-hackathon-2024-project, score: 1.00} - {ref: solutions/vmware/vmware-cloud-foundation/addon/application-services, score: 0.60}
{ "apiVersion": "soultec.ch/v1", "kind": "Post", "metadata": { "name": "powercli-find-zombie-files-on-datastores", "locale": "de", "labels": { "author": "dario-doerflinger", "series": "scripting", "capability/automation": "1.78", "vendor/vmware": "0.88" }, "annotations": { "source": "blog-content/posts/de/powercli-find-zombie-files-on-datastores.md", "route": "/de/insights/powercli-find-zombie-files-on-datastores/", "schema": "/nerd/schema/posts.json", "markdown": "/de/insights/powercli-find-zombie-files-on-datastores.md" } }, "spec": { "title": "Zombie-Dateien auf Datastores finden", "date": "2017-07-25", "author": "dario-doerflinger", "locale": "de", "summary": "RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert.", "capabilities": [ "automation" ], "vendors": [ "vmware" ], "series": "scripting", "migrated": "2026-08-24", "comments": 7, "noticeKind": "superseded", "noticeText": "RVTools und das vCenter melden verwaiste Dateien inzwischen direkt, dieses Script braucht es auf aktuellen Versionen also nicht mehr. Es bleibt hier, weil das Vorgehen erklärt, was der Report eigentlich tut.", "translationReviewed": false, "draft": false }, "sections": [ { "body": "RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert. Ohne würde ich meine Arbeit nicht machen wollen.\n\nEin Kunde wollte einen Mail-Report über die «Zombie»-Dateien auf seinen Datastores. Nach einem RVTools-Check hatte er gesehen, dass viel Platz für Snapshot-Delta-Disks draufging, die seine Backup-Lösung nicht entfernt hatte. Dieses Problem sehen wir in fast jeder Umgebung.\n\nAlso haben wir ein Script gebaut, das die Dateien meldet, die zu keiner laufenden VM gehören.\n\nBei einer grossen Umgebung braucht das Script lange, hab also Geduld. Danke an Luc aus der PowerCLI Community, der uns geholfen hat, die Funktion etwas schneller zu machen. (http://www.lucd.info/2016/09/13/orphaned-files-revisited/)\n\nUpdate: Dieses Script liegt inzwischen auf [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts)." }, { "heading": "

Das Script

",
"body": "```powershell\n##################################################################################\n# Script: RmOrphanedFiles.ps1\n# Datum: 25.07.2017\n# Version: 2.1\n# History: Added Comments\n# Replaced Add-PSSnapin with Module Command\n# Replaced Get-VmwOrphan Function\n##################################################################################\n\n[CmdletBinding(SupportsShouldProcess=$true)]\nParam(\n [parameter()]\n [String]$vCenter = \"virtualfrogvc.virtual.frog\",\n # Change to a SMTP server in your environment\n [string]$SmtpHost = \"mail.virtual.frog\",\n# Change to default email address you want emails to be coming from\n [string]$From = \"[email protected]\",\n# Change to default email address you would like to receive emails\n [Array]$To = @(\"[email protected]\",\"[email protected]\"),\n# Change to default Report Filename you like\n [string]$Attachment = \"$env:temp\\OrphanedFileReport-\"+(Get-Date -f \"yyyy-MM-dd\")+\".csv\"\n)\n\nfunction Get-VmwOrphan{\n<#\n.EXAMPLE\n PS> Get-VmwOrphaned -Datastore DS1\n.EXAMPLE\n PS> Get-Datastore -Name DS* | Get-VmwOrphaned\n#>\n\n [CmdletBinding()]\n param(\n [parameter(Mandatory=$true,ValueFromPipeline=$true)]\n [PSObject[]]$Datastore\n )\n\n Begin{\n $flags = New-Object VMware.Vim.FileQueryFlags\n $flags.FileOwner = $true\n $flags.FileSize = $true\n $flags.FileType = $true\n $flags.Modification = $true\n\n $qFloppy = New-Object VMware.Vim.FloppyImageFileQuery\n $qFolder = New-Object VMware.Vim.FolderFileQuery\n $qISO = New-Object VMware.Vim.IsoImageFileQuery\n $qConfig = New-Object VMware.Vim.VmConfigFileQuery\n $qConfig.Details = New-Object VMware.Vim.VmConfigFileQueryFlags\n $qConfig.Details.ConfigVersion = $true\n $qTemplate = New-Object VMware.Vim.TemplateConfigFileQuery\n $qTemplate.Details = New-Object VMware.Vim.VmConfigFileQueryFlags\n $qTemplate.Details.ConfigVersion = $true\n $qDisk = New-Object VMware.Vim.VmDiskFileQuery\n $qDisk.Details = New-Object VMware.Vim.VmDiskFileQueryFlags\n $qDisk.Details.CapacityKB = $true\n $qDisk.Details.DiskExtents = $true\n $qDisk.Details.DiskType = $true\n $qDisk.Details.HardwareVersion = $true\n $qDisk.Details.Thin = $true\n $qLog = New-Object VMware.Vim.VmLogFileQuery\n $qRAM = New-Object VMware.Vim.VmNvramFileQuery\n $qSnap = New-Object VMware.Vim.VmSnapshotFileQuery\n\n $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec\n $searchSpec.details = $flags\n $searchSpec.Query = $qFloppy,$qFolder,$qISO,$qConfig,$qTemplate,$qDisk,$qLog,$qRAM,$qSnap\n $searchSpec.sortFoldersFirst = $true\n }\n\n Process{\n foreach($ds in $Datastore){\n if($ds.GetType().Name -eq \"String\"){\n $ds = Get-Datastore -Name $ds\n Write-Host \"Checking Datastore $ds\"\n }\n\n# Only shared VMFS datastore\n if($ds.Type -eq \"VMFS\" -and $ds.ExtensionData.Summary.MultipleHostAccess){\n Write-Verbose -Message \"$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tLooking at $($ds.Name)\"\n\n# Define file DB\n $fileTab = @{}\n\n# Get datastore files\n $dsBrowser = Get-View -Id $ds.ExtensionData.browser\n $rootPath = \"[\" + $ds.Name + \"]\"\n $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) | Sort-Object -Property {$_.FolderPath.Length}\n foreach($folder in $searchResult){\n foreach ($file in $folder.File){\n $key = \"$($folder.FolderPath)$(if($folder.FolderPath[-1] -eq ']'){' '})$($file.Path)\"\n $fileTab.Add($key,$file)\n\n $folderKey = \"$($folder.FolderPath.TrimEnd('/'))\"\n if($fileTab.ContainsKey($folderKey)){\n $fileTab.Remove($folderKey)\n }\n }\n }\n\n# Get VM inventory\n Get-VM -Datastore $ds | %{\n $_.ExtensionData.LayoutEx.File | %{\n if($fileTab.ContainsKey($_.Name)){\n $fileTab.Remove($_.Name)\n }\n }\n }\n\n# Get Template inventory\n Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{\n $_.ExtensionData.LayoutEx.File | %{\n if($fileTab.ContainsKey($_.Name)){\n $fileTab.Remove($_.Name)\n }\n }\n }\n\n# Remove system files & folders from list\n $systemFiles = $fileTab.Keys | where{$_ -match \"] \\.|vmkdump\"}\n $systemFiles | %{\n $fileTab.Remove($_)\n }\n\n# Organise remaining files\n if($fileTab.Count){\n $fileTab.GetEnumerator() | %{\n $obj = [ordered]@{\n Name = $_.Value.Path\n Folder = $_.Name\n Size = $_.Value.FileSize\n CapacityKB = $_.Value.CapacityKb\n Modification = $_.Value.Modification\n Owner = $_.Value.Owner\n Thin = $_.Value.Thin\n Extents = $_.Value.DiskExtents -join ','\n DiskType = $_.Value.DiskType\n HWVersion = $_.Value.HardwareVersion\n }\n New-Object PSObject -Property $obj\n }\n Write-Verbose -Message \"$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tFound orphaned files on $($ds.Name)!\"\n }\n else{\n Write-Verbose -Message \"$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tNo orphaned files found on $($ds.Name).\"\n }\n }\n }\n }\n}\n\nImport-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null\nConnect-VIServer $vCenter -WarningAction SilentlyContinue | Out-Null\nWrite-Host \"Connected to $vCenter. Starting script\"\n\n$bodyh = (Get-Date -f \"yyyy-MM-dd HH:mm:ss\") + \" - the following orphaned files were found on Datastores. `n\"\n$body = Get-Datastore | Get-VmwOrphan\n$body | Export-Csv \"$Attachment\" -NoTypeInformation -UseCulture\n$body = $bodyh + ($body | Out-String)\n$subject = \"Report - orphaned Files on Datastores for $vCenter\"\nsend-mailmessage -from \"$from\" -to $to -subject \"$subject\" -body \"$body\" -Attachment \"$Attachment\" -smtpServer $SmtpHost\nDisconnect-VIServer -Server $vCenter -Force:$true -Confirm:$false\n```" } ], "status": { "corpus": 267, "alsoLike": [ { "ref": "posts/vmware-explore-las-vegas-hackathon-2025", "score": "1.00" }, { "ref": "posts/vmware-hackathon-2024-project", "score": "1.00" }, { "ref": "solutions/vmware/vmware-cloud-foundation/addon/application-services", "score": "0.60" } ] }}
apiVersion = "soultec.ch/v1"kind = "Post"[metadata]name = "powercli-find-zombie-files-on-datastores"locale = "de"[metadata.labels]author = "dario-doerflinger"series = "scripting""capability/automation" = "1.78""vendor/vmware" = "0.88"[metadata.annotations]source = "blog-content/posts/de/powercli-find-zombie-files-on-datastores.md"route = "/de/insights/powercli-find-zombie-files-on-datastores/"schema = "/nerd/schema/posts.json"markdown = "/de/insights/powercli-find-zombie-files-on-datastores.md"[spec]title = "Zombie-Dateien auf Datastores finden"date = 2017-07-25author = "dario-doerflinger"locale = "de"summary = "RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert."capabilities = ["automation"]vendors = ["vmware"]series = "scripting"migrated = 2026-08-24comments = 7noticeKind = "superseded"noticeText = "RVTools und das vCenter melden verwaiste Dateien inzwischen direkt, dieses Script braucht es auf aktuellen Versionen also nicht mehr. Es bleibt hier, weil das Vorgehen erklärt, was der Report eigentlich tut."translationReviewed = falsedraft = false[[sections]]body = '''RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert. Ohne würde ich meine Arbeit nicht machen wollen.Ein Kunde wollte einen Mail-Report über die «Zombie»-Dateien auf seinen Datastores. Nach einem RVTools-Check hatte er gesehen, dass viel Platz für Snapshot-Delta-Disks draufging, die seine Backup-Lösung nicht entfernt hatte. Dieses Problem sehen wir in fast jeder Umgebung.Also haben wir ein Script gebaut, das die Dateien meldet, die zu keiner laufenden VM gehören.Bei einer grossen Umgebung braucht das Script lange, hab also Geduld. Danke an Luc aus der PowerCLI Community, der uns geholfen hat, die Funktion etwas schneller zu machen. (http://www.lucd.info/2016/09/13/orphaned-files-revisited/)Update: Dieses Script liegt inzwischen auf [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts).'''[[sections]]heading = "

Das Script

"
body = '''```powershell################################################################################### Script: RmOrphanedFiles.ps1# Datum: 25.07.2017# Version: 2.1# History: Added Comments# Replaced Add-PSSnapin with Module Command# Replaced Get-VmwOrphan Function##################################################################################[CmdletBinding(SupportsShouldProcess=$true)]Param( [parameter()] [String]$vCenter = "virtualfrogvc.virtual.frog", # Change to a SMTP server in your environment [string]$SmtpHost = "mail.virtual.frog",# Change to default email address you want emails to be coming from [string]$From = "[email protected]",# Change to default email address you would like to receive emails [Array]$To = @("[email protected]","[email protected]"),# Change to default Report Filename you like [string]$Attachment = "$env:temp\OrphanedFileReport-"+(Get-Date -f "yyyy-MM-dd")+".csv")function Get-VmwOrphan{<#.EXAMPLE PS> Get-VmwOrphaned -Datastore DS1.EXAMPLE PS> Get-Datastore -Name DS* | Get-VmwOrphaned#> [CmdletBinding()] param( [parameter(Mandatory=$true,ValueFromPipeline=$true)] [PSObject[]]$Datastore ) Begin{ $flags = New-Object VMware.Vim.FileQueryFlags $flags.FileOwner = $true $flags.FileSize = $true $flags.FileType = $true $flags.Modification = $true $qFloppy = New-Object VMware.Vim.FloppyImageFileQuery $qFolder = New-Object VMware.Vim.FolderFileQuery $qISO = New-Object VMware.Vim.IsoImageFileQuery $qConfig = New-Object VMware.Vim.VmConfigFileQuery $qConfig.Details = New-Object VMware.Vim.VmConfigFileQueryFlags $qConfig.Details.ConfigVersion = $true $qTemplate = New-Object VMware.Vim.TemplateConfigFileQuery $qTemplate.Details = New-Object VMware.Vim.VmConfigFileQueryFlags $qTemplate.Details.ConfigVersion = $true $qDisk = New-Object VMware.Vim.VmDiskFileQuery $qDisk.Details = New-Object VMware.Vim.VmDiskFileQueryFlags $qDisk.Details.CapacityKB = $true $qDisk.Details.DiskExtents = $true $qDisk.Details.DiskType = $true $qDisk.Details.HardwareVersion = $true $qDisk.Details.Thin = $true $qLog = New-Object VMware.Vim.VmLogFileQuery $qRAM = New-Object VMware.Vim.VmNvramFileQuery $qSnap = New-Object VMware.Vim.VmSnapshotFileQuery $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec $searchSpec.details = $flags $searchSpec.Query = $qFloppy,$qFolder,$qISO,$qConfig,$qTemplate,$qDisk,$qLog,$qRAM,$qSnap $searchSpec.sortFoldersFirst = $true } Process{ foreach($ds in $Datastore){ if($ds.GetType().Name -eq "String"){ $ds = Get-Datastore -Name $ds Write-Host "Checking Datastore $ds" }# Only shared VMFS datastore if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){ Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tLooking at $($ds.Name)"# Define file DB $fileTab = @{}# Get datastore files $dsBrowser = Get-View -Id $ds.ExtensionData.browser $rootPath = "[" + $ds.Name + "]" $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) | Sort-Object -Property {$_.FolderPath.Length} foreach($folder in $searchResult){ foreach ($file in $folder.File){ $key = "$($folder.FolderPath)$(if($folder.FolderPath[-1] -eq ']'){' '})$($file.Path)" $fileTab.Add($key,$file) $folderKey = "$($folder.FolderPath.TrimEnd('/'))" if($fileTab.ContainsKey($folderKey)){ $fileTab.Remove($folderKey) } } }# Get VM inventory Get-VM -Datastore $ds | %{ $_.ExtensionData.LayoutEx.File | %{ if($fileTab.ContainsKey($_.Name)){ $fileTab.Remove($_.Name) } } }# Get Template inventory Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{ $_.ExtensionData.LayoutEx.File | %{ if($fileTab.ContainsKey($_.Name)){ $fileTab.Remove($_.Name) } } }# Remove system files & folders from list $systemFiles = $fileTab.Keys | where{$_ -match "] \.|vmkdump"} $systemFiles | %{ $fileTab.Remove($_) }# Organise remaining files if($fileTab.Count){ $fileTab.GetEnumerator() | %{ $obj = [ordered]@{ Name = $_.Value.Path Folder = $_.Name Size = $_.Value.FileSize CapacityKB = $_.Value.CapacityKb Modification = $_.Value.Modification Owner = $_.Value.Owner Thin = $_.Value.Thin Extents = $_.Value.DiskExtents -join ',' DiskType = $_.Value.DiskType HWVersion = $_.Value.HardwareVersion } New-Object PSObject -Property $obj } Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tFound orphaned files on $($ds.Name)!" } else{ Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tNo orphaned files found on $($ds.Name)." } } } }}Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-NullConnect-VIServer $vCenter -WarningAction SilentlyContinue | Out-NullWrite-Host "Connected to $vCenter. Starting script"$bodyh = (Get-Date -f "yyyy-MM-dd HH:mm:ss") + " - the following orphaned files were found on Datastores. `n"$body = Get-Datastore | Get-VmwOrphan$body | Export-Csv "$Attachment" -NoTypeInformation -UseCulture$body = $bodyh + ($body | Out-String)$subject = "Report - orphaned Files on Datastores for $vCenter"send-mailmessage -from "$from" -to $to -subject "$subject" -body "$body" -Attachment "$Attachment" -smtpServer $SmtpHostDisconnect-VIServer -Server $vCenter -Force:$true -Confirm:$false```'''[status]corpus = 267[[status.alsoLike]]ref = "posts/vmware-explore-las-vegas-hackathon-2025"score = "1.00"[[status.alsoLike]]ref = "posts/vmware-hackathon-2024-project"score = "1.00"[[status.alsoLike]]ref = "solutions/vmware/vmware-cloud-foundation/addon/application-services"score = "0.60"
<?xml version="1.0" encoding="UTF-8"?><manifest kind="Post"> <apiVersion>soultec.ch/v1</apiVersion> <metadata> <name>powercli-find-zombie-files-on-datastores</name> <locale>de</locale> <labels> <author>dario-doerflinger</author> <series>scripting</series> <entry key="capability/automation">1.78</entry> <entry key="vendor/vmware">0.88</entry> </labels> <annotations> <source>blog-content/posts/de/powercli-find-zombie-files-on-datastores.md</source> <route>/de/insights/powercli-find-zombie-files-on-datastores/</route> <schema>/nerd/schema/posts.json</schema> <markdown>/de/insights/powercli-find-zombie-files-on-datastores.md</markdown> </annotations> </metadata> <spec> <title>Zombie-Dateien auf Datastores finden</title> <date>2017-07-25</date> <author>dario-doerflinger</author> <locale>de</locale> <summary>RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert.</summary> <capabilities> <item>automation</item> </capabilities> <vendors> <item>vmware</item> </vendors> <series>scripting</series> <migrated>2026-08-24</migrated> <comments>7</comments> <noticeKind>superseded</noticeKind> <noticeText>RVTools und das vCenter melden verwaiste Dateien inzwischen direkt, dieses Script braucht es auf aktuellen Versionen also nicht mehr. Es bleibt hier, weil das Vorgehen erklärt, was der Report eigentlich tut.</noticeText> <translationReviewed>false</translationReviewed> <draft>false</draft> </spec> <sections> <section> <body>RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert. Ohne würde ich meine Arbeit nicht machen wollen.Ein Kunde wollte einen Mail-Report über die «Zombie»-Dateien auf seinen Datastores. Nach einem RVTools-Check hatte er gesehen, dass viel Platz für Snapshot-Delta-Disks draufging, die seine Backup-Lösung nicht entfernt hatte. Dieses Problem sehen wir in fast jeder Umgebung.Also haben wir ein Script gebaut, das die Dateien meldet, die zu keiner laufenden VM gehören.Bei einer grossen Umgebung braucht das Script lange, hab also Geduld. Danke an Luc aus der PowerCLI Community, der uns geholfen hat, die Funktion etwas schneller zu machen. (http://www.lucd.info/2016/09/13/orphaned-files-revisited/)Update: Dieses Script liegt inzwischen auf [GitHub](https://github.com/virtualFrog/PowerCLI-Scripts). </body> </section> <section> <heading>

Das Script

</heading>
<body>```powershell################################################################################### Script: RmOrphanedFiles.ps1# Datum: 25.07.2017# Version: 2.1# History: Added Comments# Replaced Add-PSSnapin with Module Command# Replaced Get-VmwOrphan Function##################################################################################[CmdletBinding(SupportsShouldProcess=$true)]Param( [parameter()] [String]$vCenter = "virtualfrogvc.virtual.frog", # Change to a SMTP server in your environment [string]$SmtpHost = "mail.virtual.frog",# Change to default email address you want emails to be coming from [string]$From = "[email protected]",# Change to default email address you would like to receive emails [Array]$To = @("[email protected]","[email protected]"),# Change to default Report Filename you like [string]$Attachment = "$env:temp\OrphanedFileReport-"+(Get-Date -f "yyyy-MM-dd")+".csv")function Get-VmwOrphan{&lt;#.EXAMPLE PS&gt; Get-VmwOrphaned -Datastore DS1.EXAMPLE PS&gt; Get-Datastore -Name DS* | Get-VmwOrphaned#&gt; [CmdletBinding()] param( [parameter(Mandatory=$true,ValueFromPipeline=$true)] [PSObject[]]$Datastore ) Begin{ $flags = New-Object VMware.Vim.FileQueryFlags $flags.FileOwner = $true $flags.FileSize = $true $flags.FileType = $true $flags.Modification = $true $qFloppy = New-Object VMware.Vim.FloppyImageFileQuery $qFolder = New-Object VMware.Vim.FolderFileQuery $qISO = New-Object VMware.Vim.IsoImageFileQuery $qConfig = New-Object VMware.Vim.VmConfigFileQuery $qConfig.Details = New-Object VMware.Vim.VmConfigFileQueryFlags $qConfig.Details.ConfigVersion = $true $qTemplate = New-Object VMware.Vim.TemplateConfigFileQuery $qTemplate.Details = New-Object VMware.Vim.VmConfigFileQueryFlags $qTemplate.Details.ConfigVersion = $true $qDisk = New-Object VMware.Vim.VmDiskFileQuery $qDisk.Details = New-Object VMware.Vim.VmDiskFileQueryFlags $qDisk.Details.CapacityKB = $true $qDisk.Details.DiskExtents = $true $qDisk.Details.DiskType = $true $qDisk.Details.HardwareVersion = $true $qDisk.Details.Thin = $true $qLog = New-Object VMware.Vim.VmLogFileQuery $qRAM = New-Object VMware.Vim.VmNvramFileQuery $qSnap = New-Object VMware.Vim.VmSnapshotFileQuery $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec $searchSpec.details = $flags $searchSpec.Query = $qFloppy,$qFolder,$qISO,$qConfig,$qTemplate,$qDisk,$qLog,$qRAM,$qSnap $searchSpec.sortFoldersFirst = $true } Process{ foreach($ds in $Datastore){ if($ds.GetType().Name -eq "String"){ $ds = Get-Datastore -Name $ds Write-Host "Checking Datastore $ds" }# Only shared VMFS datastore if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){ Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tLooking at $($ds.Name)"# Define file DB $fileTab = @{}# Get datastore files $dsBrowser = Get-View -Id $ds.ExtensionData.browser $rootPath = "[" + $ds.Name + "]" $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) | Sort-Object -Property {$_.FolderPath.Length} foreach($folder in $searchResult){ foreach ($file in $folder.File){ $key = "$($folder.FolderPath)$(if($folder.FolderPath[-1] -eq ']'){' '})$($file.Path)" $fileTab.Add($key,$file) $folderKey = "$($folder.FolderPath.TrimEnd('/'))" if($fileTab.ContainsKey($folderKey)){ $fileTab.Remove($folderKey) } } }# Get VM inventory Get-VM -Datastore $ds | %{ $_.ExtensionData.LayoutEx.File | %{ if($fileTab.ContainsKey($_.Name)){ $fileTab.Remove($_.Name) } } }# Get Template inventory Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{ $_.ExtensionData.LayoutEx.File | %{ if($fileTab.ContainsKey($_.Name)){ $fileTab.Remove($_.Name) } } }# Remove system files &amp; folders from list $systemFiles = $fileTab.Keys | where{$_ -match "] \.|vmkdump"} $systemFiles | %{ $fileTab.Remove($_) }# Organise remaining files if($fileTab.Count){ $fileTab.GetEnumerator() | %{ $obj = [ordered]@{ Name = $_.Value.Path Folder = $_.Name Size = $_.Value.FileSize CapacityKB = $_.Value.CapacityKb Modification = $_.Value.Modification Owner = $_.Value.Owner Thin = $_.Value.Thin Extents = $_.Value.DiskExtents -join ',' DiskType = $_.Value.DiskType HWVersion = $_.Value.HardwareVersion } New-Object PSObject -Property $obj } Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tFound orphaned files on $($ds.Name)!" } else{ Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tNo orphaned files found on $($ds.Name)." } } } }}Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-NullConnect-VIServer $vCenter -WarningAction SilentlyContinue | Out-NullWrite-Host "Connected to $vCenter. Starting script"$bodyh = (Get-Date -f "yyyy-MM-dd HH:mm:ss") + " - the following orphaned files were found on Datastores. `n"$body = Get-Datastore | Get-VmwOrphan$body | Export-Csv "$Attachment" -NoTypeInformation -UseCulture$body = $bodyh + ($body | Out-String)$subject = "Report - orphaned Files on Datastores for $vCenter"send-mailmessage -from "$from" -to $to -subject "$subject" -body "$body" -Attachment "$Attachment" -smtpServer $SmtpHostDisconnect-VIServer -Server $vCenter -Force:$true -Confirm:$false``` </body> </section> </sections> <status> <corpus>267</corpus> <alsoLike> <item> <ref>posts/vmware-explore-las-vegas-hackathon-2025</ref> <score>1.00</score> </item> <item> <ref>posts/vmware-hackathon-2024-project</ref> <score>1.00</score> </item> <item> <ref>solutions/vmware/vmware-cloud-foundation/addon/application-services</ref> <score>0.60</score> </item> </alsoLike> </status></manifest>
Scripting · 2017-07-25

Zombie-Dateien auf Datastores finden

RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert.

2017-07-25Datum
Dario DörflingerAutor
3Min. Lesezeit
Themen Automation 1.78
Hersteller VMware 0.88

Dieser Beitrag ist von 2017. Er bleibt online, weil er nach wie vor nachgefragt wird, beschreibt aber einen Produktstand von damals.

RVTools kennt in unserer Branche jeder. Ein grossartiges Werkzeug, das für Infrastruktur-Checks in kurzer Zeit sehr viel liefert. Ohne würde ich meine Arbeit nicht machen wollen.

Ein Kunde wollte einen Mail-Report über die «Zombie»-Dateien auf seinen Datastores. Nach einem RVTools-Check hatte er gesehen, dass viel Platz für Snapshot-Delta-Disks draufging, die seine Backup-Lösung nicht entfernt hatte. Dieses Problem sehen wir in fast jeder Umgebung.

Also haben wir ein Script gebaut, das die Dateien meldet, die zu keiner laufenden VM gehören.

Bei einer grossen Umgebung braucht das Script lange, hab also Geduld. Danke an Luc aus der PowerCLI Community, der uns geholfen hat, die Funktion etwas schneller zu machen. (http://www.lucd.info/2016/09/13/orphaned-files-revisited/)

Update: Dieses Script liegt inzwischen auf GitHub.

Das Script

##################################################################################
# Script:           RmOrphanedFiles.ps1
# Datum:            25.07.2017
# Version:          2.1
# History:          Added Comments
#                   Replaced Add-PSSnapin with Module Command
#                   Replaced Get-VmwOrphan Function
##################################################################################

[CmdletBinding(SupportsShouldProcess=$true)]
Param(
  [parameter()]
  [String]$vCenter = "virtualfrogvc.virtual.frog",
  # Change to a SMTP server in your environment
  [string]$SmtpHost = "mail.virtual.frog",
# Change to default email address you want emails to be coming from
    [string]$From = "[email protected]",
# Change to default email address you would like to receive emails
    [Array]$To = @("[email protected]","[email protected]"),
# Change to default Report Filename you like
    [string]$Attachment = "$env:temp\OrphanedFileReport-"+(Get-Date -f "yyyy-MM-dd")+".csv"
)

function Get-VmwOrphan{
<#
.EXAMPLE
  PS> Get-VmwOrphaned -Datastore DS1
.EXAMPLE
  PS> Get-Datastore -Name DS* | Get-VmwOrphaned
#>

  [CmdletBinding()]
  param(
    [parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [PSObject[]]$Datastore
  )

  Begin{
    $flags = New-Object VMware.Vim.FileQueryFlags
    $flags.FileOwner = $true
    $flags.FileSize = $true
    $flags.FileType = $true
    $flags.Modification = $true

    $qFloppy = New-Object VMware.Vim.FloppyImageFileQuery
    $qFolder = New-Object VMware.Vim.FolderFileQuery
    $qISO = New-Object VMware.Vim.IsoImageFileQuery
    $qConfig = New-Object VMware.Vim.VmConfigFileQuery
    $qConfig.Details = New-Object VMware.Vim.VmConfigFileQueryFlags
    $qConfig.Details.ConfigVersion = $true
    $qTemplate = New-Object VMware.Vim.TemplateConfigFileQuery
    $qTemplate.Details = New-Object VMware.Vim.VmConfigFileQueryFlags
    $qTemplate.Details.ConfigVersion = $true
    $qDisk = New-Object VMware.Vim.VmDiskFileQuery
    $qDisk.Details = New-Object VMware.Vim.VmDiskFileQueryFlags
    $qDisk.Details.CapacityKB = $true
    $qDisk.Details.DiskExtents = $true
    $qDisk.Details.DiskType = $true
    $qDisk.Details.HardwareVersion = $true
    $qDisk.Details.Thin = $true
    $qLog = New-Object VMware.Vim.VmLogFileQuery
    $qRAM = New-Object VMware.Vim.VmNvramFileQuery
    $qSnap = New-Object VMware.Vim.VmSnapshotFileQuery

    $searchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
    $searchSpec.details = $flags
    $searchSpec.Query = $qFloppy,$qFolder,$qISO,$qConfig,$qTemplate,$qDisk,$qLog,$qRAM,$qSnap
    $searchSpec.sortFoldersFirst = $true
  }

  Process{
    foreach($ds in $Datastore){
      if($ds.GetType().Name -eq "String"){
        $ds = Get-Datastore -Name $ds
        Write-Host "Checking Datastore $ds"
      }

# Only shared VMFS datastore
      if($ds.Type -eq "VMFS" -and $ds.ExtensionData.Summary.MultipleHostAccess){
        Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tLooking at $($ds.Name)"

# Define file DB
        $fileTab = @{}

# Get datastore files
        $dsBrowser = Get-View -Id $ds.ExtensionData.browser
        $rootPath = "[" + $ds.Name + "]"
        $searchResult = $dsBrowser.SearchDatastoreSubFolders($rootPath, $searchSpec) | Sort-Object -Property {$_.FolderPath.Length}
        foreach($folder in $searchResult){
          foreach ($file in $folder.File){
            $key = "$($folder.FolderPath)$(if($folder.FolderPath[-1] -eq ']'){' '})$($file.Path)"
            $fileTab.Add($key,$file)

            $folderKey = "$($folder.FolderPath.TrimEnd('/'))"
            if($fileTab.ContainsKey($folderKey)){
              $fileTab.Remove($folderKey)
            }
          }
        }

# Get VM inventory
        Get-VM -Datastore $ds | %{
          $_.ExtensionData.LayoutEx.File | %{
            if($fileTab.ContainsKey($_.Name)){
              $fileTab.Remove($_.Name)
            }
          }
        }

# Get Template inventory
        Get-Template | where {$_.DatastoreIdList -contains $ds.Id} | %{
          $_.ExtensionData.LayoutEx.File | %{
            if($fileTab.ContainsKey($_.Name)){
              $fileTab.Remove($_.Name)
            }
          }
        }

# Remove system files & folders from list
        $systemFiles = $fileTab.Keys | where{$_ -match "] \.|vmkdump"}
        $systemFiles | %{
          $fileTab.Remove($_)
        }

# Organise remaining files
        if($fileTab.Count){
          $fileTab.GetEnumerator() | %{
            $obj = [ordered]@{
              Name = $_.Value.Path
              Folder = $_.Name
              Size = $_.Value.FileSize
              CapacityKB = $_.Value.CapacityKb
              Modification = $_.Value.Modification
              Owner = $_.Value.Owner
              Thin = $_.Value.Thin
              Extents = $_.Value.DiskExtents -join ','
              DiskType = $_.Value.DiskType
              HWVersion = $_.Value.HardwareVersion
            }
            New-Object PSObject -Property $obj
          }
          Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tFound orphaned files on $($ds.Name)!"
        }
        else{
          Write-Verbose -Message "$(Get-Date)`t$((Get-PSCallStack)[0].Command)`tNo orphaned files found on $($ds.Name)."
        }
      }
    }
  }
}

Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue | Out-Null
Connect-VIServer $vCenter -WarningAction SilentlyContinue | Out-Null
Write-Host "Connected to $vCenter. Starting script"

$bodyh = (Get-Date -f "yyyy-MM-dd HH:mm:ss") + "  -  the following orphaned files were found on Datastores. `n"
$body = Get-Datastore | Get-VmwOrphan
$body | Export-Csv "$Attachment" -NoTypeInformation -UseCulture
$body = $bodyh + ($body | Out-String)
$subject = "Report - orphaned Files on Datastores for $vCenter"
send-mailmessage -from "$from" -to $to -subject "$subject" -body "$body" -Attachment "$Attachment" -smtpServer $SmtpHost
Disconnect-VIServer -Server $vCenter -Force:$true -Confirm:$false

Passt ausserdem