none
Verzeichnisgröße auslesen

    Frage

  • Guten Morgen,

    ich möchte auf einer Freigabe die Größen mehrerer Verzeichnisse abfragen. Derzeit mache ich pro Verzeichnis eine eigene Abfrage die so aussieht:

    $SrvName = "\\" + $Srv + "\d$\Install"

    If(Test-Path $SrvName) { $sum = (Get-ChildItem -Path $SrvName -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum 'Install Size: {0:n2} GB' -f ($sum/1GB) | Out-File -FilePath $_Link -Append } Else {'Install Size: nicht vorhanden.' | Out-File -FilePath $_Link -Append }

    Da es aber fünf Verzeichnisse sind und die Server per WAN angebunden sind, dauern die fünf Abfragen auf einem Server schon mal 45-60 Minuten.

    Hat jemand eine Idee wie ich das schneller hinbekomme, vielleicht in nur einer Abfrage.

    Vielen Dank

    Norbert


    IT Berater

    Mittwoch, 5. Dezember 2018 08:52

Antworten

  • ... verstanden habe ist der Punkt mit dem robocopy. wo nutzt das wie?
    hmmmm ... na ich hoffe mal, ich trete jetzt keine Diskussion über Code-Qualität los ...  hier die Funktion:
    Function Get-FolderInfo{
        [CmdletBinding()]
        [OutputType([System.String])]
        param(
            [Parameter(ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true, 
            Position=0)]
            [ValidateNotNullOrEmpty()]
            [System.IO.DirectoryInfo[]]
            $Path = (Get-Location).Path
        )
        begin {
            try {
                If(Get-Variable Matches -ea 0){
                    Remove-Variable Matches
                }
            } catch {
                throw
            }
        }
        process {
            try {
                Foreach($InputObject in $Path){
                    $Result = robocopy "$($InputObject.FullName)" "c:\temp" /zb /e /l /r:0 /w:0 /nfl /ndl /nc /fp /bytes /np /njh /XJ /XJD /XJF
                    $Result | Where-Object {$_ -match "(Dateien|Files\s)\:\s+(\d+)\s"} | Out-Null
                    $Count = "{0,9:0,0}" -f [INT]$Matches[2]
                    
                    $Result | Where-Object {$_ -match "(Verzeich\.|Dirs\s)\:\s+(\d+)\s"} | Out-Null
                    $SubFolders = "{0,10:0,0}" -f [INT]$Matches[2]
    
                    $Size = "{0,12:n2}" -f  [math]::Round((($Result | Where-Object {$_ -match "Bytes"}).trim().split(" ")[2])/1MB ,2)
                    
    				[PSCustomObject]@{
    					"Path" = $InputObject.FullName 
    					"Subfolders" = $SubFolders
    					"FileCount" = $Count
    					"Size    (MB)" = $Size
    				}
                }
            } catch {
                throw
            }
        }
    }



    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Mittwoch, 5. Dezember 2018 10:49

Alle Antworten

  • Die Anzahl der Anfragen dürfte in diesem Fall kaum den Flaschenhals darstellen. Es wird wohl eher die WAN-Verbindung sein. Hast Du eine Möglichkeit, Dich mit dem Server direkt zu verbinden und den Code "lokal" auszuführen? z.B. mit PSRemoting?

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Mittwoch, 5. Dezember 2018 08:56
  • Ja ich kann mich verbinden, aber ich möchte mich nicht mit 15 Servern verbinden :)

    Die Ordner haben zum Teile eine Größe von 200GB, dass auszurechnen dauert sicherlich seine Zeit. 


    IT Berater

    Mittwoch, 5. Dezember 2018 09:35
  • Ja ich kann mich verbinden, aber ich möchte mich nicht mit 15 Servern verbinden :)

    ;-) ... ich hatte ja nicht vorgeschlagen es "zu Fuß" zu machen. Wir sind hier im Powershell Forum .... das geht auch mittels Scripting ... automatisiert sozusagen.

    Die Ordner haben zum Teile eine Größe von 200GB, dass auszurechnen dauert sicherlich seine Zeit.

    Was heißt "seine Zeit"? Mit Sicherheit nicht Minuten. Wenn man noch ein bissl trickst - z.B. robocopy einspannt - dauert es für ein 200 GB großes Verzeichnis nur 2 oder 3 Sekunden


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Mittwoch, 5. Dezember 2018 09:50
  • Ich habe das Script seit 8:57 Uhr laufen. Der erste Server steht noch in LAN und ging in der Tat recht schnell.
    Im Anschluss wurden vier Server überprüft und jetzt läuft Nr. 5. 

    Das ist was ich meine mit "seine Zeit". Mein Wunsch wäre es ein Verzeichnis abzufragen und die nächste Ebene der Ordner dann auswerten zu können.

    Beispiel:

    \\Server\Share$\Ordner\ 

    \\Server\Share$\Ordner\Ordner1 - 4 GB
    \\Server\Share$\Ordner\Ordner2 - 10 GB
    \\Server\Share$\Ordner\Ordner3 - 90 GB


    IT Berater

    Mittwoch, 5. Dezember 2018 10:00
  • Ich hab grad mal ein bissl gespielt. Wir haben einen FileServer und dort hab ich mal die oberste Verzeichnisebene "abgegrast". Get-FolderInfo ist selbst gebastelt und benutzt robocopy um die angezeigten Infos einzusammeln.

    PS C:\> Get-ChildItem d: | Get-FolderInfo 
    
    Path                       Subfolders                 FileCount                 Size    (MB)             
    ----                       ----------                 ---------                 ------------             
    D:\...                         50.223                   451.042                   203.289,17             
    D:\...                          5.834                    57.204                    23.912,15             
    D:\...                         12.407                    96.564                    91.764,41             
    D:\...                         45.177                   369.206                   209.101,82             
    D:\.......                     43.070                   419.619                   236.511,72             
    D:\....                        13.752                   147.030                    59.618,56             
    D:\...                         55.287                   511.576                   329.342,55             
    D:\.......                     69.043                   588.367                   300.612,94             
    D:\................                01                        03                         0,00             
    D:\...................             09                        45                         0,00             
    D:\.......                         01                        00                         0,00             
    D:\.....                       19.189                   217.250                   140.676,92             
    D:\...                          6.195                    56.064                    64.677,99             
    D:\.......                         58                       196                        10,49   
    Die Ordnernmamen hab ich mal "geschwärzt". ;-)  ... ich hab dann mal gemessen, wie lange die Aktion gedauert hat:
    PS C:\> Measure-Command -Expression {Get-ChildItem D: | Get-FolderInfo }
    
    
    Days              : 0
    Hours             : 0
    Minutes           : 0
    Seconds           : 27
    Milliseconds      : 24
    Ticks             : 270244044
    TotalDays         : 0,000312782458333333
    TotalHours        : 0,007506779
    TotalMinutes      : 0,45040674
    TotalSeconds      : 27,0244044
    TotalMilliseconds : 27024,4044
    Wie Du siehst, dauert das keine Minuten. Es sind gute 1,5 TB und das braucht knapp 28 Sekunden.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''



    • Bearbeitet BOfH_666 Mittwoch, 5. Dezember 2018 10:13
    Mittwoch, 5. Dezember 2018 10:09
  • Das probiere ich gleich mal aus. Was ich noch nicht so ganz verstanden habe ist der Punkt mit dem robocopy. wo nutzt das wie?

    IT Berater

    Mittwoch, 5. Dezember 2018 10:40
  • ... verstanden habe ist der Punkt mit dem robocopy. wo nutzt das wie?
    hmmmm ... na ich hoffe mal, ich trete jetzt keine Diskussion über Code-Qualität los ...  hier die Funktion:
    Function Get-FolderInfo{
        [CmdletBinding()]
        [OutputType([System.String])]
        param(
            [Parameter(ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true, 
            Position=0)]
            [ValidateNotNullOrEmpty()]
            [System.IO.DirectoryInfo[]]
            $Path = (Get-Location).Path
        )
        begin {
            try {
                If(Get-Variable Matches -ea 0){
                    Remove-Variable Matches
                }
            } catch {
                throw
            }
        }
        process {
            try {
                Foreach($InputObject in $Path){
                    $Result = robocopy "$($InputObject.FullName)" "c:\temp" /zb /e /l /r:0 /w:0 /nfl /ndl /nc /fp /bytes /np /njh /XJ /XJD /XJF
                    $Result | Where-Object {$_ -match "(Dateien|Files\s)\:\s+(\d+)\s"} | Out-Null
                    $Count = "{0,9:0,0}" -f [INT]$Matches[2]
                    
                    $Result | Where-Object {$_ -match "(Verzeich\.|Dirs\s)\:\s+(\d+)\s"} | Out-Null
                    $SubFolders = "{0,10:0,0}" -f [INT]$Matches[2]
    
                    $Size = "{0,12:n2}" -f  [math]::Round((($Result | Where-Object {$_ -match "Bytes"}).trim().split(" ")[2])/1MB ,2)
                    
    				[PSCustomObject]@{
    					"Path" = $InputObject.FullName 
    					"Subfolders" = $SubFolders
    					"FileCount" = $Count
    					"Size    (MB)" = $Size
    				}
                }
            } catch {
                throw
            }
        }
    }



    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Mittwoch, 5. Dezember 2018 10:49
  • Das probiere ich gleich mal aus.
    ... und?  ... magst Du uns auch noch mitteilen, was bei der Probe rausgekommen ist?

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Sonntag, 9. Dezember 2018 16:53
  • Hi, ich hab versucht deine Funktion zu nutzen, aber egal ob ich einen lokalen Pfad ("c:") oder FQDN als STRING übergebe oder ein Filesystem-Objekt (Get-Item c:) ich erhalte immer nur den Fehler:
    "Es ist nicht möglich, einen Index auf ein NULL-Array anzuwenden.
    An ...test.ps1:Zeile:26 Zeichen:17"

    Grüße, Robert


    • Bearbeitet RobertWe Dienstag, 11. Dezember 2018 12:34
    Dienstag, 11. Dezember 2018 12:33
  • Dann solltest Du den Code "debuggen"! ;-) :-D  Du hast aber nicht zufällig ein Windows mit einer anderen Systemsprache als Deutsch oder English, oder?

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 11. Dezember 2018 13:23
  • Nö, Deutsch.

    Und wenn ich das debuggen könnte, hätte ich nicht gefragt. :)

    Dienstag, 11. Dezember 2018 13:28
  • Debuggen ist ja keine Rocket-Science. Du führst den Code in der ISE oder in VSCode zeilenweise aus und siehst Dir die Ergebnisse an ... schaust, welche Werte die Variablen annhemen ... oder führst Kommandozeilen z.B. nur bis zur nächsten Pipe aus und schaust Dir das Ergebnis an ...

    Ich kann ja Deinen Bildschirm nicht sehen und bei mir läuft der Code.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 11. Dezember 2018 13:42