Aktionen

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.

Hinweis:Natürlich kann die Ausführung des Skriptes eine ganze weile dauern, schließlich fragt es tatsächlich jede Datei einmal ab um den echten letzten Zeitpunkt zu ermitteln.

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

Kommentare

Loading comments...