Falsche Berechnung in Powershellscript
Hallo Zusammen,
seit kurzem beschäftige ich mich etwas mit Powershell und habe da (für mich) ein sehr interessantes Phänomen.
Das Script soll mir die Ordnergrößen mehrerer Ordner und zum Schluß die Summe ausgeben.
Solange wie ich das in der ISE teste ist alles so wie ich es haben möchte aber sobald ich entweder die xx.ps1 direkt aufrufe oder über eine Batch zeigt er als Summe nur noch den letzten abgefragten Wert an und da stehe ich etwas auf dem Schlauch und würde mich freuen wenn mir da jemand meinen Denkfehler zeigen könnte.
Das Script:
Als Ergebnis erhalte ich dann (richtig):
Pfad Größe
-----
C:\Users\xyz\Desktop 0,004 GB
C:\Users\xyz\Documents 0,000 GB
C:\UserData\xyz\Downloads 6,926 GB
Summe der Ordner: 6,930 GB
Als Ergebnis erhalte ich dann (falsch):
Pfad Größe
-----
C:\Users\xyz\Desktop 0,004 GB
C:\Users\xyz\Documents 0,000 GB
C:\UserData\xyz\Downloads 6,926 GB
Summe der Ordner: 6,926 GB
seit kurzem beschäftige ich mich etwas mit Powershell und habe da (für mich) ein sehr interessantes Phänomen.
Das Script soll mir die Ordnergrößen mehrerer Ordner und zum Schluß die Summe ausgeben.
Solange wie ich das in der ISE teste ist alles so wie ich es haben möchte aber sobald ich entweder die xx.ps1 direkt aufrufe oder über eine Batch zeigt er als Summe nur noch den letzten abgefragten Wert an und da stehe ich etwas auf dem Schlauch und würde mich freuen wenn mir da jemand meinen Denkfehler zeigen könnte.
Das Script:
$Folders = @(
"$env:USERPROFILE\Desktop"
"$env:USERPROFILE\Documents"
"$env:USERPROFILE\Downloads"
)
$total = 0
'Größe der Ordner:'
#ForEach ($Folder in ($Folders)) {"$_ : {0:n3} GB" -f ((Get-ChildItem -Path $_ -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).sum/1GB)}
& {
ForEach ($_ in ($Folders))
{
$sum1 = (Get-ChildItem -Path $_ -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).sum
New-Object psobject -Property @{
Pfad = $_
Größe = '{0:n3} GB' -f ($sum1/1GB)
}
$Global:total = $total + $sum1
}
} | Format-Table -auto Pfad,Größe
'Summe der Ordner: {0:n3} GB' -f (($Global:total)/1GB)
Als Ergebnis erhalte ich dann (richtig):
Pfad Größe
-----
C:\Users\xyz\Desktop 0,004 GB
C:\Users\xyz\Documents 0,000 GB
C:\UserData\xyz\Downloads 6,926 GB
Summe der Ordner: 6,930 GB
Als Ergebnis erhalte ich dann (falsch):
Pfad Größe
-----
C:\Users\xyz\Desktop 0,004 GB
C:\Users\xyz\Documents 0,000 GB
C:\UserData\xyz\Downloads 6,926 GB
Summe der Ordner: 6,926 GB
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 1821571299
Url: https://administrator.de/forum/falsche-berechnung-in-powershellscript-1821571299.html
Ausgedruckt am: 11.04.2025 um 19:04 Uhr
6 Kommentare
Neuester Kommentar
Hi
du hantierst hier aus einer Mischung zwischen GLOBAL und LOCAL Variablen.
Global funktioniert in der ISE nicht wirklich, weil es im Grunde Zeile für Zeile einzeln ausführt und damit Global und Local das gleiche ist.
Das wird deutlich wenn du dein Script mal um 2 Ausgaben erweiterst:
Ausgabe in der ISE:
Ausgabe als PS1:
Du siehst im ISE das die Größen aufeinander addiert werden
und im PS1 das einzelnen größen einfach aufgelistet werden.
Das liegt daran das in der .ps1 deine Zeile
Dafür Sorgt das immer ausgeführt wird:
$Global:total ist Jetzt: 0 + Grösse
und nicht
$Global:total ist Jetzt: $Global:total + Grösse
Einfach weil du Local und Global vermischt. deine Variable $total ist immer 0, weil sie nie verändert wird
Du solltest also schreiben:
oder besser den Quatsch mit dem manuellen summieren lassen und dein CustomObject auch nutzen.
Für was du da den call einbaust erschliesst sich mir allerdings überhaupt nicht.
Ich würde eher sowas basteln:
du hantierst hier aus einer Mischung zwischen GLOBAL und LOCAL Variablen.
Global funktioniert in der ISE nicht wirklich, weil es im Grunde Zeile für Zeile einzeln ausführt und damit Global und Local das gleiche ist.
Das wird deutlich wenn du dein Script mal um 2 Ausgaben erweiterst:
$Global:total = $total + $sum1
Write-Host "Total im FE: $($Global:total/1GB)"
}
Write-Host "Total NACH FE: $($Global:total/1GB)"
$result | Format-Table -auto Pfad,Größe
Ausgabe in der ISE:
Größe der Ordner:
Total im FE: 0.0578269734978676
Total im FE: 0.0697913477197289
Total im FE: 36.6269341837615
Total NACH FE: 36.6269341837615
Pfad Größe
---- -----
C:\Users\SeaStorm\Desktop 0,058 GB
C:\Users\SeaStorm\Documents 0,012 GB
C:\Users\SeaStorm\Downloads 36,557 GB
Summe der Ordner: 36,627 GB
Ausgabe als PS1:
Größe der Ordner:
Total im FE: 0.0578269734978676
Total im FE: 0.0119643742218614
Total im FE: 36.5571428360417
Total NACH FE: 36.5571428360417
Pfad Größe
---- -----
C:\Users\SeaStorm\Desktop 0,058 GB
C:\Users\SeaStorm\Documents 0,012 GB
C:\Users\SeaStorm\Downloads 36,557 GB
Summe der Ordner: 36,557 GB
Du siehst im ISE das die Größen aufeinander addiert werden
und im PS1 das einzelnen größen einfach aufgelistet werden.
Das liegt daran das in der .ps1 deine Zeile
$Global:total = $total + $sum1
$Global:total ist Jetzt: 0 + Grösse
und nicht
$Global:total ist Jetzt: $Global:total + Grösse
Einfach weil du Local und Global vermischt. deine Variable $total ist immer 0, weil sie nie verändert wird
Du solltest also schreiben:
$Global:total = 0
....
$Global:total = $Global:total + $sum1
oder besser den Quatsch mit dem manuellen summieren lassen und dein CustomObject auch nutzen.
Für was du da den call einbaust erschliesst sich mir allerdings überhaupt nicht.
Ich würde eher sowas basteln:
$Folders = @(
"$env:USERPROFILE\Desktop"
"$env:USERPROFILE\Documents"
"$env:USERPROFILE\Downloads"
)
'Größe der Ordner:'
$FolderResult = ForEach ($_ in ($Folders))
{
$sum1 = (Get-ChildItem -Path $_ -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).sum
New-Object psobject -Property @{
Pfad = $_
Größe = $sum1/1GB
}
}
$FolderResult | Format-Table -auto Pfad, @{name=’Größssse’ ; expression={"{0:n3}" -f $_.Größe}}
'Summe der Ordner: {0:n3} GB' -f (( ($FolderResult.Größe | Measure -Sum).Sum))
Zitat von @mabe12:
$Folders = @(
"$env:USERPROFILE\Desktop"
"$env:USERPROFILE\Documents"
"$env:USERPROFILE\Downloads"
)
Sollte zur Bestimmung dieser Ordner nicht eher
GetFolderPath
[Environment]::GetFolderPath("Desktop")
Jain. $FolderResult kommt ja von mir. Du hast ein Object mit
New-Object psobject -Property ....
erstellt, machst aber nichts damit, ausser es in das Format-Table zu pipen.
Deine Zeile 12 : "& {"
& ist hier ein Call Operator. Also "& { SCRIPT BLOCK }" um den Scriptblock auszuführen. Ergibt hier einfach keinen Sinn, außer das du das Ergebnis jetzt halt pipen kannst. Dann lieber in eine Variable packen damit man das ganze auch verwenden kann. Ausserdem ist's super hässlich zu lesen
New-Object psobject -Property ....
erstellt, machst aber nichts damit, ausser es in das Format-Table zu pipen.
Für was du da den call einbaust erschliesst sich mir allerdings überhaupt nicht.
Was genau meinst du damit?& ist hier ein Call Operator. Also "& { SCRIPT BLOCK }" um den Scriptblock auszuführen. Ergibt hier einfach keinen Sinn, außer das du das Ergebnis jetzt halt pipen kannst. Dann lieber in eine Variable packen damit man das ganze auch verwenden kann. Ausserdem ist's super hässlich zu lesen
Zitat von @mabe12:
@mbehrens
das kannte ich so noch nicht und was ich nicht verstehe ist wenn ich das so aufrufe bekomme ich den Pfad, genau so wie er benötigt wird.
Wenn ich Get-ChildItem env: aufrufe erhalte ich keinen "Desktop" - woher wird das dann genommen?
Was genau ist der Unterschied bzw Vor- und Nachteile von
"$env:USERPROFILE\Desktop" und [Environment]::GetFolderPath("Desktop")
das kannte ich so noch nicht und was ich nicht verstehe ist wenn ich das so aufrufe bekomme ich den Pfad, genau so wie er benötigt wird.
Wenn ich Get-ChildItem env: aufrufe erhalte ich keinen "Desktop" - woher wird das dann genommen?
Was genau ist der Unterschied bzw Vor- und Nachteile von
"$env:USERPROFILE\Desktop" und [Environment]::GetFolderPath("Desktop")
Dier erste Version benutzt einen Pfad, der auf Umgebungsvariable Userprofile basiert. Dort wird einfach "\Desktop" angehängt. Dieses Verzeichnis (C:\Users\meinBenutzer\Desktop) muss es nicht zwangsläufig geben, z. B. wenn der Desktop umgeleitet ist. Die zweite Version liefert dann den richtigen Pfad (\\meinServer\meineFreigabe\meinBenuzter\Desktop).