Ordnergrößen mittels Powershell ermitteln
Hallo zusammen,
ich würde gerne folgendes mit Hilfe der Powershell lösen.
Ich habe auf einem Server einen Ordner, nennen wir ihn "basisordner" und diesem sind mehrere unterordner mit wiederum unterordnern.
Ich möchte nun mittels Powershell alle Unterordner unter Basisordner auflisten und deren Größe ermitteln.
Bsp.:
Basisordner
\Unterordner 1
-\Unterordner 11
\Unterordner 2
\Unterordner 3
-\Unterordner 31
-\Unterordner 32
Als Ergebnis soll rauskommen:
Unterordner 1 1GB
Unterordner 2 500 MB
Unterordner 3 3GB
Ich denke mal dass das vorgehen so wäre, erst alle Ordner aufzulisten und dann die Dateigrößen aller Ordner (bzw. unterordner) zu summieren.
Die Ausgabe als TXT / CSV wäre ideal.
Gruß
Edit: Habe da etwas gefunden: http://technet.microsoft.com/en-us/library/ff730945
als txt kann ich das mittels Scriptaufruf und Ausgabeumleitung machen. Lässt sich dies denn noch eleganter lösen?
Edit2: Ich bekomme oft die Meldung, dass der Dateipfad zu lang ist
ich würde gerne folgendes mit Hilfe der Powershell lösen.
Ich habe auf einem Server einen Ordner, nennen wir ihn "basisordner" und diesem sind mehrere unterordner mit wiederum unterordnern.
Ich möchte nun mittels Powershell alle Unterordner unter Basisordner auflisten und deren Größe ermitteln.
Bsp.:
Basisordner
\Unterordner 1
-\Unterordner 11
\Unterordner 2
\Unterordner 3
-\Unterordner 31
-\Unterordner 32
Als Ergebnis soll rauskommen:
Unterordner 1 1GB
Unterordner 2 500 MB
Unterordner 3 3GB
Ich denke mal dass das vorgehen so wäre, erst alle Ordner aufzulisten und dann die Dateigrößen aller Ordner (bzw. unterordner) zu summieren.
Die Ausgabe als TXT / CSV wäre ideal.
Gruß
Edit: Habe da etwas gefunden: http://technet.microsoft.com/en-us/library/ff730945
als txt kann ich das mittels Scriptaufruf und Ausgabeumleitung machen. Lässt sich dies denn noch eleganter lösen?
Edit2: Ich bekomme oft die Meldung, dass der Dateipfad zu lang ist
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 221755
Url: https://administrator.de/forum/ordnergroessen-mittels-powershell-ermitteln-221755.html
Ausgedruckt am: 07.04.2025 um 22:04 Uhr
10 Kommentare
Neuester Kommentar
Hallo killtec,
http://social.technet.microsoft.com/Forums/scriptcenter/en-US/dedfd9e2- ...
Grüße Uwe
Edit2: Ich bekomme oft die Meldung, dass der Dateipfad zu lang ist face-sad
das mit den überlangen Pfaden größer 248 Zeichen ist schon Lange ein Problem von .Net:http://social.technet.microsoft.com/Forums/scriptcenter/en-US/dedfd9e2- ...
Grüße Uwe
Ohne jetzt das Problem mit den überlangen Pfaden zu beachten(experimentiere noch an einer Lösung) kannst du die Größen der Ordner nach Größe sortiert folgendermaßen in eine CSV-Datei exportieren:
Zeile 16 und 17 anpassen.
Grüße Uwe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function parseFolders($sFolder){
$allFolders = get-childitem $sFolder -ErrorAction SilentlyContinue |?{$_.PSIsContainer}
foreach ($f in $allFolders){
$size = (get-childitem $f.FullName -ErrorAction SilentlyContinue | ?{!($_.PSIsContainer)} | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum
$folderSum += $size
parseFolders $f.FullName
if ($f.Parent.FullName -eq $global:startFolder){
echo "$($f.FullName) hat eine Größe von $([MATH]::Round($folderSum / (1024*1024),2)) MB"
$global:folderList += New-Object PSObject -Property @{"Ordner"=$f.FullName;"Größe"="$([MATH]::Round($folderSum / (1024*1024),2)) MB"}
$folderSum = 0
}
}
}
$global:startFolder = "C:\temp\source"
$csvDatei = "C:\temp\test.csv"
$global:folderList = @()
parseFolders $startFolder
$global:folderList | select Ordner,Größe | Sort-Object -Property Größe -Descending | Export-Csv -Path $csvDatei -Delimiter ";" -NoTypeInformation -Encoding UTF8
Grüße Uwe
Dann eliminiere zuerst die langen Pfade.
Um zu ermitteln welche Pfade mehr wie 248 Zeichen haben, kannst du folgende Funktion nutzen:
(Den Startpfad gibst du in der letzten Zeile des Scripts ein)
Die Funktion entstammt im Ursprung von hier, wurde aber von mir verbessert. Sie benötigt als Voraussetzung das 'robocopy' installiert ist.
Es ist ein Witz das MS den Umstand mit den langen Pfaden noch nicht mal mit PS4.0 bzw. Net 4.5 behoben hat...
Grüße Uwe
Um zu ermitteln welche Pfade mehr wie 248 Zeichen haben, kannst du folgende Funktion nutzen:
(Den Startpfad gibst du in der letzten Zeile des Scripts ein)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Function Get-LongPaths {
param(
[CmdletBinding()]
[Parameter(
Position=0,
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]
$FolderPath,
[ValidateRange(10,248)]
[int]
$MaxChars=248
)
begin {
if (!(Test-Path -Path $(Join-Path $env:SystemRoot 'System32\robocopy.exe'))) {
write-warning "Robocopy wurde nicht gefunden, bitte installieren Sie Robocopy um diese Funktion nutzen zu können!"
return
}
}
process {
$regex = [Regex] "\t"
foreach ($Path in $FolderPath) {
$RoboOutput = robocopy.exe $Path c:\temp /l /e /b /np /fp /njh /njs /r:0 /w:0
$RoboOutput | Where-Object {$_} |
ForEach-Object {
$CurrentPath = $regex.Split($_)[2]
if ($CurrentPath.Length -gt $MaxChars) {
New-Object -TypeName PSCustomObject -Property @{
FullName = $CurrentPath
PfadLänge = $CurrentPath.Length
Type = if ($CurrentPath.SubString($CurrentPath.Length-1,1) -eq '\') {
'Ordner'
} else {
'Datei'
}
}
}
}
}
}
}
Get-LongPaths -FolderPath 'C:\Startpfad'
Es ist ein Witz das MS den Umstand mit den langen Pfaden noch nicht mal mit PS4.0 bzw. Net 4.5 behoben hat...
Grüße Uwe
Zitat von @killtec:
ist es richtig, dass die Asugabe leer bleibt? In Zeile 27 hast du noch das Verzeichnis c:\temp stehen. das wäre dann das Zeil
korrekt?
Wird dies nur als temporär genutzt, bzw. nur dazu, dass ein Verzeichnis da steht? Das Verzeichnis gibt es bei mir z.b.
nicht.
Das Verzeichnis C:\temp ist nur ein Dummy für Robocopy es wird nicht erstellt bzw. muss nicht existieren.ist es richtig, dass die Asugabe leer bleibt? In Zeile 27 hast du noch das Verzeichnis c:\temp stehen. das wäre dann das Zeil
korrekt?
Wird dies nur als temporär genutzt, bzw. nur dazu, dass ein Verzeichnis da steht? Das Verzeichnis gibt es bei mir z.b.
nicht.
Wenn die Ausgabe leer ist, sind in dem Ordner und Unterordnern keine überlangen Ordnernamen.
Hier geht diese Überprüfung einwandfrei (PS3.0 Win7x64).
Hallo,
ich setz mal hier an.
Da die obigen Powershell-Befehle auf Fehler laufen.(Die Aufruftiefe hat 1001erreicht. Der Höchstwert lautet 1000.)
Sind diese an den Start gekommen:
In Content2.txt stehen ca.100 Einträge.
Dauer ca. 25min.
Gibt es paar Kniffe die Abfrage zu beschleunigen?
Über Tips und Vorschläge wäre ich sehr dankbar.
Grüße
René
ich setz mal hier an.
Da die obigen Powershell-Befehle auf Fehler laufen.(Die Aufruftiefe hat 1001erreicht. Der Höchstwert lautet 1000.)
Sind diese an den Start gekommen:
1
2
3
4
5
2
3
4
5
$Content = Get-Content 'c:\Schreiben\Content2.txt'
foreach($Content in $content)
{$colItems = (Get-ChildItem $content -recurse | Measure-Object -property length -sum)
"$content" + " " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"
}
Dauer ca. 25min.
Gibt es paar Kniffe die Abfrage zu beschleunigen?
Über Tips und Vorschläge wäre ich sehr dankbar.
Grüße
René
tach auch,
du verwendest zwei gleich lautende Variablen in deinem ForEach() Konstrukt: $Content und $content das solltest du unbedingt vermeiden und eine separate Variable verwenden:
ansonsten nutze mal testweise u.s. Code. Denke zwar das es nicht viel schneller sein wird, aber das ist nun mal in Windows so, dass dies seine Zeit dauert. In der Win32 API gibt es auch keine schnellere Methode. Selbst der Windows Explorer benötigt hier eben solange wenn man die Eigenschaften für einen Ordner aufruft der zig tausende Files und Unterordner beinhaltet.
Grüße Uwe
du verwendest zwei gleich lautende Variablen in deinem ForEach() Konstrukt: $Content und $content das solltest du unbedingt vermeiden und eine separate Variable verwenden:
1
2
3
4
5
2
3
4
5
$Content = Get-Content 'c:\Schreiben\Content2.txt'
foreach($line in $content){
$colItems = (Get-ChildItem $line -recurse | Measure-Object -property length -sum)
"$line" + " " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function initCode() {
[String]$SourceCode = @"
Namespace colinardo
Public Class MyFunctions
Public Shared Function GetDirectorySize(ByVal sPath As String) As Long
Dim lngSize As Long = 0
Try
Dim diDir As New System.io.DirectoryInfo(sPath)
Dim file As System.io.FileInfo
For Each file In diDir.GetFiles()
lngSize += file.Length
Next
Dim subDirInfo As System.io.DirectoryInfo
For Each subDirInfo In diDir.GetDirectories()
lngSize += GetDirectorySize(subDirInfo.FullName)
Next
Catch ex as System.Exception
End Try
Return lngSize
End Function
End Class
End Namespace
"@
add-type -TypeDefinition $SourceCode -Language VisualBasic
}
initCode
$Content = Get-Content 'c:\Schreiben\Content2.txt'
foreach($line in $content){
"$line" + " " + "{0:N2}" -f ([colinardo.MyFunctions]::GetDirectorySize($line) / 1MB) + " MB"
}
Grüße Uwe