PowerShell Ordnergröße mit letzten echten Änderungsdatum rekursiv 1 Ebene
Aus znilwiki
Changelog:
- 21.07.2026 erste Version
Vorwort
Bei einem Kunden habe ich einen Dateiserver / Fileserver analysiert. Dabei ging es neben den Ordnergrößen auch darum, ob Ordner überhaupt noch genutzt werden.
Problem 1 waren die Zugriffsrechte, im Dateiexplorer wurde vieles unterschlagen, die Abfrage sollte also per PowerShell erfolgen da man diese "als Administrator" ausführen kann.
Problem 2 war der letzte Zugriff. Das Änderungsdatum des Hauptordners ändert sich nicht, wenn die letzte Änderung tiefer im Dateisystem stattfand.
Das nachfolgende Skript gibt so etwas aus:
PS C:\> E:\Get-FolderStats.ps1 "E:\Seafile\" Name Letzte Änderung Größe (GiB) ---- --------------- ----------- Excel 03.04.2023 13:26:28 1,93 JavaScript-Schulung 12.12.2023 23:47:55 0,01 Test-Daten1 03.07.2026 09:05:36 0,04 Test-Daten2 22.04.2023 08:25:58 50,79 Installationen 19.12.2018 09:08:06 12,79 Meine Bibliothek 08.06.2019 06:55:16 0 RoyalTS_Portable 01.06.2022 09:49:42 0,26 TAUSCH 09.11.2020 10:50:03 0,03 Uploads 15.06.2023 16:27:22 0,02 ZNIL-Dokumentation 18.07.2026 00:35:08 0,07
Alphabetisch sortiert, Letzte Änderung entspricht der Realität sowie die Größe in GiB.
Als erweiterte Version gibt das Skript zusätzlich die Anzahl der Ordner und Dateien aus:
PS C:\> E:\Get-FolderStatsExtented.ps1 "E:\Seafile\" Name Unterordner Dateien Letzte Aenderung Groesse (GiB) ---- ----------- ------- ---------------- ------------- Excel 38 232 03.04.2023 13:26:28 1,93 JavaScript-Schulung 223 1.367 12.12.2023 23:47:55 0,01 Test-Daten1 27 442 03.07.2026 09:05:36 0,04 Test-Daten2 17.874 91.774 22.04.2023 08:25:58 50,79 Installationen 5.006 12.055 19.12.2018 09:08:06 12,79 Meine Bibliothek 0 2 08.06.2019 06:55:16 0,00 RoyalTS_Portable 61 998 01.06.2022 09:49:42 0,26 TAUSCH 0 1 09.11.2020 10:50:03 0,03 Uploads 0 2 15.06.2023 16:27:22 0,02 ZNIL-Dokumentation 27 116 18.07.2026 00:35:08 0,07
Die Skripts wurden mit Google Gemini erstellt.
Skript Simpel
Als Dateiname habe ich
Get-FolderStats.ps1
gewählt, wegen der Umlaute sollte das Dateiformat UTF-8-BOM sein:
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
# Prüfen, ob der Pfad existiert
if (-not (Test-Path -Path $Path)) {
Write-Error "Der angegebene Pfad '$Path' wurde nicht gefunden."
return
}
# Alle Unterordner der 1. Ebene abrufen
$subfolders = Get-ChildItem -Path $Path -Directory
$results = foreach ($folder in $subfolders) {
# Alle Dateien im Unterordner rekursiv abrufen
$files = Get-ChildItem -Path $folder.FullName -Recurse -File -ErrorAction SilentlyContinue
if ($files) {
# Summe der Dateigrößen in GiB berechnen (1GB in PS entspricht 1024^3 Bytes, also 1 GiB)
$totalBytes = ($files | Measure-Object -Property Length -Sum).Sum
$sizeGiB = [math]::Round($totalBytes / 1GB, 2)
# Neuestes Änderungsdatum aller enthaltenen Dateien ermitteln
$lastModified = ($files | Measure-Object -Property LastWriteTime -Maximum).Maximum
} else {
# Falls der Ordner komplett leer ist oder keine Dateien enthält
$sizeGiB = 0
$lastModified = $folder.LastWriteTime
}
# Objekt für die Ausgabe erstellen
[PSCustomObject]@{
Name = $folder.Name
'Letzte Änderung' = $lastModified
'Größe (GiB)' = $sizeGiB
}
}
# Alphabetisch nach Name sortieren und als Tabelle ausgeben
$results | Sort-Object Name | Format-Table -AutoSize
Skript Erweitert
Diese Version gibt zusätzlich die Anzahl der Dateien und Ordner mit an:
Als Dateiname habe ich
Get-FolderStatsExtended.ps1
gewählt, wegen der Umlaute sollte das Dateiformat UTF-8-BOM sein:
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
# Prüfen, ob der Pfad existiert
if (-not (Test-Path -Path $Path)) {
Write-Error "Der angegebene Pfad '$Path' wurde nicht gefunden."
return
}
# Alle Unterordner der 1. Ebene abrufen
$subfolders = Get-ChildItem -Path $Path -Directory
$results = foreach ($folder in $subfolders) {
# Alle Dateien im Unterordner rekursiv abrufen
$files = Get-ChildItem -Path $folder.FullName -Recurse -File -ErrorAction SilentlyContinue
# Alle tieferen Unterordner rekursiv abrufen
$subDirs = Get-ChildItem -Path $folder.FullName -Recurse -Directory -ErrorAction SilentlyContinue
$subDirCount = if ($subDirs) { $subDirs.Count } else { 0 }
if ($files) {
$fileCount = $files.Count
$totalBytes = ($files | Measure-Object -Property Length -Sum).Sum
$sizeGiB = [math]::Round($totalBytes / 1GB, 2)
$lastModified = ($files | Measure-Object -Property LastWriteTime -Maximum).Maximum
} else {
$fileCount = 0
$sizeGiB = 0
$lastModified = $folder.LastWriteTime
}
# Objekt erstellen (Zahlen bleiben echte Datentypen für die Ausrichtung)
[PSCustomObject]@{
Name = $folder.Name
SubDirCount = [int]$subDirCount
FileCount = [int]$fileCount
'Letzte Aenderung' = $lastModified
GroesseGiB = [double]$sizeGiB
}
}
# Ausgabefortschritt: Formatierung mit Tausendertrennzeichen und Rechtsbündigkeit
$results | Sort-Object Name | Format-Table `
Name, `
@{Name='Unterordner'; Expression={$_.SubDirCount}; FormatString='N0'; Align='Right'}, `
@{Name='Dateien'; Expression={$_.FileCount}; FormatString='N0'; Align='Right'}, `
'Letzte Aenderung', `
@{Name='Groesse (GiB)'; Expression={$_.GroesseGiB}; FormatString='N2'; Align='Right'} `
-AutoSize
Skript Erweitert mit Fortschrittsanzeige
Wie zuvor, jedoch mit Fortschrittsanzeige:
Als Dateiname habe ich
Get-FolderStatsExtended.ps1
gewählt, wegen der Umlaute sollte das Dateiformat UTF-8-BOM sein:
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
# Prüfen, ob der Pfad existiert
if (-not (Test-Path -Path $Path)) {
Write-Error "Der angegebene Pfad '$Path' wurde nicht gefunden."
return
}
# Alle Unterordner der 1. Ebene abrufen
$subfolders = Get-ChildItem -Path $Path -Directory
$totalFolders = $subfolders.Count
$currentIndex = 0
$results = foreach ($folder in $subfolders) {
$currentIndex++
# Prozentuale Berechung für den Ladebalken
$percentComplete = [math]::Round(($currentIndex / $totalFolders) * 100)
# Fortschrittsanzeige in der Konsole einblenden
Write-Progress -Activity "Analysiere Ordnerstruktur" `
-Status "Verarbeite Ordner $currentIndex von $totalFolders ($percentComplete%)" `
-CurrentOperation $folder.Name `
-PercentComplete $percentComplete
# Alle Dateien im Unterordner rekursiv abrufen
$files = Get-ChildItem -Path $folder.FullName -Recurse -File -ErrorAction SilentlyContinue
# Alle tieferen Unterordner rekursiv abrufen
$subDirs = Get-ChildItem -Path $folder.FullName -Recurse -Directory -ErrorAction SilentlyContinue
$subDirCount = if ($subDirs) { $subDirs.Count } else { 0 }
if ($files) {
$fileCount = $files.Count
$totalBytes = ($files | Measure-Object -Property Length -Sum).Sum
$sizeGiB = [math]::Round($totalBytes / 1GB, 2)
$lastModified = ($files | Measure-Object -Property LastWriteTime -Maximum).Maximum
} else {
$fileCount = 0
$sizeGiB = 0
$lastModified = $folder.LastWriteTime
}
# Objekt erstellen
[PSCustomObject]@{
Name = $folder.Name
SubDirCount = [int]$subDirCount
FileCount = [int]$fileCount
'Letzte Aenderung' = $lastModified
GroesseGiB = [double]$sizeGiB
}
}
# Fortschrittsanzeige nach Abschluss wieder ausblenden
Write-Progress -Activity "Analysiere Ordnerstruktur" -Completed
# Ausgabe mit rechtsbündiger Formatierung
$results | Sort-Object Name | Format-Table `
Name, `
@{Name='Unterordner'; Expression={$_.SubDirCount}; FormatString='N0'; Align='Right'}, `
@{Name='Dateien'; Expression={$_.FileCount}; FormatString='N0'; Align='Right'}, `
'Letzte Aenderung', `
@{Name='Groesse (GiB)'; Expression={$_.GroesseGiB}; FormatString='N2'; Align='Right'} `
-AutoSizeparam(
[Parameter(Mandatory=$true)]
[string]$Path
)
# Prüfen, ob der Pfad existiert
if (-not (Test-Path -Path $Path)) {
Write-Error "Der angegebene Pfad '$Path' wurde nicht gefunden."
return
}
# Alle Unterordner der 1. Ebene abrufen
$subfolders = Get-ChildItem -Path $Path -Directory
$totalFolders = $subfolders.Count
$currentIndex = 0
$results = foreach ($folder in $subfolders) {
$currentIndex++
# Prozentuale Berechung für den Ladebalken
$percentComplete = [math]::Round(($currentIndex / $totalFolders) * 100)
# Fortschrittsanzeige in der Konsole einblenden
Write-Progress -Activity "Analysiere Ordnerstruktur" `
-Status "Verarbeite Ordner $currentIndex von $totalFolders ($percentComplete%)" `
-CurrentOperation $folder.Name `
-PercentComplete $percentComplete
# Alle Dateien im Unterordner rekursiv abrufen
$files = Get-ChildItem -Path $folder.FullName -Recurse -File -ErrorAction SilentlyContinue
# Alle tieferen Unterordner rekursiv abrufen
$subDirs = Get-ChildItem -Path $folder.FullName -Recurse -Directory -ErrorAction SilentlyContinue
$subDirCount = if ($subDirs) { $subDirs.Count } else { 0 }
if ($files) {
$fileCount = $files.Count
$totalBytes = ($files | Measure-Object -Property Length -Sum).Sum
$sizeGiB = [math]::Round($totalBytes / 1GB, 2)
$lastModified = ($files | Measure-Object -Property LastWriteTime -Maximum).Maximum
} else {
$fileCount = 0
$sizeGiB = 0
$lastModified = $folder.LastWriteTime
}
# Objekt erstellen
[PSCustomObject]@{
Name = $folder.Name
SubDirCount = [int]$subDirCount
FileCount = [int]$fileCount
'Letzte Aenderung' = $lastModified
GroesseGiB = [double]$sizeGiB
}
}
# Fortschrittsanzeige nach Abschluss wieder ausblenden
Write-Progress -Activity "Analysiere Ordnerstruktur" -Completed
# Ausgabe mit rechtsbündiger Formatierung
$results | Sort-Object Name | Format-Table `
Name, `
@{Name='Unterordner'; Expression={$_.SubDirCount}; FormatString='N0'; Align='Right'}, `
@{Name='Dateien'; Expression={$_.FileCount}; FormatString='N0'; Align='Right'}, `
'Letzte Aenderung', `
@{Name='Groesse (GiB)'; Expression={$_.GroesseGiB}; FormatString='N2'; Align='Right'} `
-AutoSize
