danielbodensee
Goto Top

Dateien rekursiv durchgehen

Hallo zusammen,

ich möchte ein Script schreiben mit dem ich unsere File-Server durchgehen möchte um Dateien rekursiv durchzugehen um diese in einer SQL-Tabelle zu erfassen. Ziel ist nach einem Dateimuster zu suchen (Datum-/Zeit-Angabe im Filename wie ...26.03.2019_11_15_00...).

Wenn ich mit "Get-ChildItem -Path \\ServerName\Pfad -Recurse" starte, wird das Script erst mal alle Files erfassen damit ich dann das Ergebnis durchgehen kann oder kann ich sofort Aktionen durchführen um den Dateinamen in eine SQL Tabelle einzufügen?

Ist das der beste Weg oder eher über Objekte?

Gruss,
Daniel

Content-ID: 432754

Url: https://administrator.de/forum/dateien-rekursiv-durchgehen-432754.html

Ausgedruckt am: 22.12.2024 um 19:12 Uhr

138810
138810 26.03.2019 aktualisiert um 18:47:50 Uhr
Goto Top
Wenn ich mit "Get-ChildItem -Path \\ServerName\Pfad -Recurse" starte, wird das Script erst mal alle Files erfassen damit ich dann das Ergebnis durchgehen kann oder kann ich sofort Aktionen durchführen um den Dateinamen in eine SQL Tabelle einzufügen?
Ist das der beste Weg oder eher über Objekte?
Je nachdem wie du arbeitest kannst du das Verhalten anpassen:

Folgendes liest erst mal alle Dateien in eine Variable ein und durchläuft diese Daten dann mit einer Schleife. Diese Variante fängt mit der eigentlichen Arbeit also erst an wenn alle Dateien in die Variable eingelesen sind (Bei vielen Dateien kann das einiges an Arbeitsspeicher kosten).
$variable = gci '\\Server\Pfad' -File -Recurse  
foreach ($file in $files){
    # mach hier was für jedes File
}
Im Gegensatz dazu wird folgende Variante schon beim Suchen der Dateien diese an die in der Pipline weitergeben, so wie die gefundenen Dateien durch Get-Childitem gefunden werden. Diese Variante ist vor allem dann vorteilhaft wenn man Speicher sparen möchte, ist aber im Allgemeinen insgesamt dafür etwas langsamer dafür werden eben schon Dateien verarbeitet wo bei der anderen Variante noch gewartet werden muss bis alle Files gefunden wurden.
gci '\\Server\Pfad' -File -Recurse | %{  
   # mach hier was für jedes File
}
Du kannst also abwägen was dir wichtiger ist. Speicher sparen und initial eine längere Pause zum Einlesen der Dateien, oder die prompte Verarbeitung über die Pipeline so wie die Objekte aus Get-ChildItem eintreffen und Speicher sparen.

Ziel ist nach einem Dateimuster zu suchen (Datum-/Zeit-Angabe im Filename wie ...26.03.2019_11_15_00...).
Das Ausfiltern der Dateien kannst du ja mit einem Where-Object machen z.B. so für dein Beispiel oben:
gci '\\Server\Pfad' -File -Recurse | ?{$_.Basename -match '\d{2}\.\d{2}\.\d{4}_\d{2}_\d{2}_\d{2}'}  

Statt aber für jedes File eine extra INSERT INTO Anweisung zu machen würde ich die Daten in ein Array schreiben und das ganze dann in einer einzigen Insert Anweisung oder blockweise in die Datenbank schieben. Kommt halt insgesamt drauf an was noch so alles geschehen soll.
DanielBodensee
DanielBodensee 26.03.2019 um 19:33:34 Uhr
Goto Top
Hi,

vielen Dank für die Ausführung, genau das war meine Frage face-smile

Ich habe geschätzt 40.000 Files einzulesen, denke ich mache das sicherheitshalber mit der zweiten Variante face-smile

Danke auch für den Ansatz mit der Suche nach dem Datum/Uhrzeit-Stamp, das hilft mir schon mal sehr viel weiter.

Viele Grüsse,
Daniel
77559
77559 26.03.2019 um 20:05:33 Uhr
Goto Top
Zitat von @138810:
Ziel ist nach einem Dateimuster zu suchen (Datum-/Zeit-Angabe im Filename wie ...26.03.2019_11_15_00...).
Das Ausfiltern der Dateien kannst du ja mit einem Where-Object machen z.B. so für dein Beispiel oben:
> gci '\\Server\Pfad' -File -Recurse | ?{$_.Basename -match '\d{2}\.\d{2}\.\d{4}_\d{2}_\d{2}_\d{2}'}  
> 

Meistens wird ja nicht nach einem exakten Datum gesucht, sondern mit einem Referenzdatum vor/nach verglichen.

Da der -match operator den/die gefundenen Werte in der automatischen Variable $Matches ablegt, kann man nach Where-Object das gefundene Datum in den Typ [datetime] mit ::ParseExact() umwandeln und dann Zeitvergleiche anstellen.

Erzeuge Testdateien vom 1. bis 31. diesen Monats

1..31|%{New-Item -ItemType file -Name ("foo_{0:dd.MM.yyyy\_HH\_mm\_ss}_bar.txt" -f (Get-Date -day $_))}  

Testscript das nur Dateien mit DatumZeit größer als $RefDatum (jetzt) ausgibt.
$RefDatum = [datetime]::now
$Folder = '.'  

Get-ChildItem $Folder -File -Recurse | 
  Where-Object {$_.Basename -match '\d{2}\.\d{2}\.\d{4}_\d{2}_\d{2}_\d{2}' -and  
   ([datetime]::ParseExact($Matches.Values,"dd.MM.yyyy\_HH\_mm\_ss",[cultureinfo]::InvariantCulture)) -gt $RefDatum}  

Beispiel Ausgabe

    Verzeichnis: A:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019-03-26     19:39              0 foo_27.03.2019_19_39_50_bar.txt
-a----       2019-03-26     19:39              0 foo_28.03.2019_19_39_50_bar.txt
-a----       2019-03-26     19:39              0 foo_29.03.2019_19_39_50_bar.txt
-a----       2019-03-26     19:39              0 foo_30.03.2019_19_39_50_bar.txt
-a----       2019-03-26     19:39              0 foo_31.03.2019_19_39_50_bar.txt

Gruß
LotPings