Powershell - Geschwindigkeit Dateisuche
Ich habe das Problem, dass eine Suche nach einer Datei extrem lange dauert, obwohl ich dem Befehl schon Grundsätze zur Einschränkung vorgebe.
Das Verzeichnis ist in der Regel so aufgebaut:
c:\suchverzeichnis\ordner1\ordner2\ordner3\log\server.log
Da sich die Namen ordner1\ordner2\ ändern können, beginne ich also nur bei c:\suchverzeichnis
Der komische Effekt ist, dass wenn man den Befehl absendet, die Datei innerhalb von circa 2 Sekunden gefunden wird, er die Suche dann aber nicht aufhört, sondern weitersucht. Der endliche Abbruch der Suche kann dann bis zu 5 Minuten dauern.
Warum?
Jemand einen Tipp?
Get-ChildItem -Path c:\suchverzeichnis -Recurse -ErrorAction SilentlyContinue -Force -Filter "server.log" | Select-Object -First 1
Das Verzeichnis ist in der Regel so aufgebaut:
c:\suchverzeichnis\ordner1\ordner2\ordner3\log\server.log
Da sich die Namen ordner1\ordner2\ ändern können, beginne ich also nur bei c:\suchverzeichnis
Der komische Effekt ist, dass wenn man den Befehl absendet, die Datei innerhalb von circa 2 Sekunden gefunden wird, er die Suche dann aber nicht aufhört, sondern weitersucht. Der endliche Abbruch der Suche kann dann bis zu 5 Minuten dauern.
Warum?
Jemand einen Tipp?
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 353957
Url: https://administrator.de/contentid/353957
Ausgedruckt am: 25.11.2024 um 09:11 Uhr
16 Kommentare
Neuester Kommentar
Hi,
Man müsste also schon im ersten Kommando auf "Abbruch bei erstem Treffer" eingrenzen.
E.
er die Suche dann aber nicht aufhört, sondern weitersucht. Der endliche Abbruch der Suche kann dann bis zu 5 Minuten dauern.
Weil das de facto zwei unabhängige Kommando sind, welche nur in einer Pipe verkettet sind.Select-Object -First 1
Sagt bloß aus, dass der nur das erste Objekt dessen liefern soll, wasGet-ChildItem -Path c:\suchverzeichnis -Recurse -ErrorAction SilentlyContinue -Force -Filter "server.log"
liefert. "Get-ChildItem" muss aber u.U. tausende Dateien/Verzeichnisse durchsuchen, um alle Ergebnisse zu liefern.Man müsste also schon im ersten Kommando auf "Abbruch bei erstem Treffer" eingrenzen.
E.
hm, welche PS Version benutzt du?
(kann man z.B. rausfinden indem man die Variable $PSVersionTable abfragt)
Bei mir (PS v5.1) funktioniert es wie von dir "gewünscht": Bei | Select-Object -First 1 hört er nach dem ersten Treffer auf zu suchen.
Wenn man nur den Get-ChildItem befehl ausführt, werden die Ergebnisse eins nach dem anderen angezeigt d.h. eigentlich sollte es so mit der pipe funktionieren...
(kann man z.B. rausfinden indem man die Variable $PSVersionTable abfragt)
Bei mir (PS v5.1) funktioniert es wie von dir "gewünscht": Bei | Select-Object -First 1 hört er nach dem ersten Treffer auf zu suchen.
Wenn man nur den Get-ChildItem befehl ausführt, werden die Ergebnisse eins nach dem anderen angezeigt d.h. eigentlich sollte es so mit der pipe funktionieren...
Wer verstehen will wie die Pipeline arbeitet, sollte
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ...
lesen, besonders den Abschnitt, One-At-a-time Processing.
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ...
lesen, besonders den Abschnitt, One-At-a-time Processing.
Da sich die Namen ordner1\ordner2\ ändern können, beginne ich also nur bei c:\suchverzeichnis
Nicht nötig wenn du den Ordner so bei Get-Childitem angibst.C:\suchverzeichnis\*\*
Servus,
die Powershell Version ist hier essentiell denn
https://docs.microsoft.com/de-de/powershell/module/Microsoft.PowerShell. ...
Ein Windows 7 ohne Update des Management Frameworks hätte diese Optimierungs als nicht, da es per Default mit PS 2.0 ausgeliefert wird.
Wichtig ist ebenfalls das keine Klammern um den Get-Childitem Befehl gesetzt werden da ansonsten erst das gesamte Array erstellt werden muss bevor es in der Pipe weitergeleitet wird.
Grüße Uwe
die Powershell Version ist hier essentiell denn
Beginning in Windows PowerShell 3.0, Select-Object includes an optimization feature that prevents commands from creating and processing objects that are not used. When you include a Select-Object command with the First or Index parameter in a command pipeline, Windows PowerShell stops the command that generates the objects as soon as the selected number of objects is generated, even when the command that generates the objects appears before the Select-Object command in the pipeline. To turn off this optimizing behavior, use the Wait parameter.
Ein Windows 7 ohne Update des Management Frameworks hätte diese Optimierungs als nicht, da es per Default mit PS 2.0 ausgeliefert wird.
Wichtig ist ebenfalls das keine Klammern um den Get-Childitem Befehl gesetzt werden da ansonsten erst das gesamte Array erstellt werden muss bevor es in der Pipe weitergeleitet wird.
Grüße Uwe
Danke @colinardo , gut zu wissen!
C$ nicht möglich, weil keine Adminrechte vorhanden.
Na dann eine explizite Freigabe dafür einrichten.Praktisch ist es aber ja dasselbe wie der Befehl "invoke-command -computer Server -credential user -scriptblock {gci -path c:\suchverzeichnis usw}
Nein. Wenn Du das über Netzwerk (Zugriff auf Freigabe) laufen lässt, dann gilt die Powershell-Version des Computers, wo das Script läuft. Darum ging es mir.
Doch du machst es nur falsch.
gci 'c:\suchverzeichnis\*\*' -recurse -Filter 'server.log' -Force
Du kannst dir auch deine eigene Rekursive Funktion bauen das ist Versionsunabhängig.
function Find-FirstFile([string]$path,[string]$filter){
$result = gci $path -Filter $filter -Force | select -First 1
if ($result){
return $result
}else{
gci $path | ?{$_.PSIsContainer} | %{Find-FirstFile $_.Fullname -Filter $filter}
}
}
Find-FirstFile "C:\suchverzeichnis" "server.log"
@specht
Schön und gut, aber noch der wichtige Hinweis: Das wird nur so lange gute gehen bis Powershell sagt "Nope, mehr wie Rekursionstiefe 100 will ich nicht!". Deswegen sollte man diese Konstrukte in Powershell bei der Verarbeitung von unbekannten Dateisystem-Bäumen immer möglichst vermeiden und die Rekursion umbauen, z.B. in einen While Loop oder das vorherige enumerieren aller Ordner und dann mit Schleife darüber.
https://weblogs.asp.net/jongalloway/working-around-a-powershell-call-dep ...
Rekursive Funktionen sind mit eine der häufigsten Ursachen von Stack-Overflows, so please use with care!.
Schön und gut, aber noch der wichtige Hinweis: Das wird nur so lange gute gehen bis Powershell sagt "Nope, mehr wie Rekursionstiefe 100 will ich nicht!". Deswegen sollte man diese Konstrukte in Powershell bei der Verarbeitung von unbekannten Dateisystem-Bäumen immer möglichst vermeiden und die Rekursion umbauen, z.B. in einen While Loop oder das vorherige enumerieren aller Ordner und dann mit Schleife darüber.
https://weblogs.asp.net/jongalloway/working-around-a-powershell-call-dep ...
Rekursive Funktionen sind mit eine der häufigsten Ursachen von Stack-Overflows, so please use with care!.