leax55
Goto Top

Powershell: Text in Textdatei finden und als Ordnername vergeben

Hallo Zusammen,

wie im Titel bereits steht, benötige ich ein Script um in einem Ordner, in dem mehrere Textdateien liegen, nach einem bestimmten Text zu suchen, und diesen dann als Ordnernamen einem neu erstellten Ordner zu vergeben. Die Textdatei soll dann in diesen Ordner verschoben werden.

Im Detail:

  • Ordner mit mehreren Textdateien wird Datei für Datei nach einem bestimmten Text im Inhalt durchsucht.
  • Nicht der gefundene Text sondern das was rechts daneben steht, muss einer Variable zugewiesen werden. Bsp: in der Datei gibt es eine Stelle wo steht "Bestellnr: 12345" -> es wird nach "Bestellnr:" gesucht -> wenn gefunden, soll "12345" in eine Variable.
  • Anschließend soll ein neuer Ordner erstellt werden und der Inhalt der Variable als Ordnername verwendet werden.
  • Zuletzt soll die Datei in diesen Ordner verschoben werden (Alle Dateien mit identischer Bestellnr).

Als Hinweis noch vllt dass der Text "Bestellnr: XXXXX" in jeder Datei immer vorhanden ist und auch immer in gleicher Position. Evtl. könnte man also auch nach xy Koordinaten gehen anstatt Text zu suchen?

Ich hoffe ich konnte es verständlich erklären.

Ich würde mich freuen wenn Ihr mir ein paar Codebeispiele oder Links nennen könnt mit dem ich arbeiten kann.

Bin leider noch nicht so fit in Powershell.

Alles was ich zusammenbauen konnte ist bisher das:
$Pfad = 'C:\Neuer Ordner'  
$Suchbegriff='Bestellnr:'  

ForEach-Object(Get-ChildItem $Pfad | Select-String $Suchbegriff)

Bis dahin verstehs ichs noch aber dann für jede Textdatei in der eine andere Bestellnr ist, einen neuen Ordner anlegen und die richtige Textdatei in den Ordner zu verschieben, ist für mich eine Herausforderung.

Vielen Dank schonmal

Content-Key: 666020

Url: https://administrator.de/contentid/666020

Ausgedruckt am: 19.03.2024 um 05:03 Uhr

Mitglied: 148121
Lösung 148121 22.04.2021 aktualisiert um 16:53:36 Uhr
Goto Top
Moin.
# Pfad in den der neue Ordner erstellt wird
$pfad = 'C:\RootOrdner'  
$found = Select-String 'D:\Ordner\*.txt' -Pattern "Bestellnr:\s*(\d+)" -list | %{  
    # neuen Ordnernamen aus dem regex Submatch extrahieren und mit Root-Ordner zu einem Pfad zusammensetzen
    $subordner = join-path $pfad $_.Matches.Groups[1].Value
    # neuen Ordner erstellen
    md  $subordner -Force | out-null
    # und Datei rein kopieren
    move-item -Path $_.Path -Destination $subordner
}
Gruß w.

p.s. Lektüre für Anfänger findest du hier in diesem Kommentar:
Zeichen zählen, um Zeilenläge zu begrenzen
Mitglied: LeaX55
LeaX55 22.04.2021 um 19:33:03 Uhr
Goto Top
Hi warranty,

hat beim ersten Versuch geklappt.
MEGA!!
Vielen Dank für die schnelle Lösung!

kannst Du mir vllt noch kurz erklären was das \s*(\d+) nach der Bestellnr bedeutet?
Und eine Zeile drunter das Matches.Groups[1].Value

Konnte darüber nirgends was gescheites finden.

Wie muss der Code eigentlich aussehen wenn die Nr unterhalb von "Bestellnr" steht statt rechts daneben?
Also so:
Bestellnr:
XXXXX
Mitglied: 148121
148121 22.04.2021, aktualisiert am 23.04.2021 um 15:18:30 Uhr
Goto Top
Zitat von @LeaX55:
kannst Du mir vllt noch kurz erklären was das \s*(\d+) nach der Bestellnr bedeutet?
Das sind Regular Expressions und bedeutet matche 0 oder mehrere Leerzeichen worauf Mindestens 1 oder mehrere Nummern folgen, welche durch die Klammern in einen Submatch geladen werden.

Und eine Zeile drunter das Matches.Groups[1].Value
Damit greife ich auf den oben geklammerten Submatch im Regex (also die Nummer) zu

Wie muss der Code eigentlich aussehen wenn die Nr unterhalb von "Bestellnr" steht statt rechts daneben?
Also so:
Bestellnr:
XXXXX

Das ist dann ein klein wenig anders mit Select-String weil das zeilenweise arbeitet, aber dafür hat es den Parameter -Context
# Pfad in den der neue Ordner erstellt wird
$pfad = 'C:\RootOrdner'  
$found = Select-String 'D:\Ordner\*.txt' -Pattern "Bestellnr:" -list -Context 1 | %{  
    # neuen Ordnernamen aus dem regex Submatch extrahieren und mit Root-Ordner zu einem Pfad zusammensetzen
    $subordner = join-path $pfad $_.Context.PostContext.split(' ')  
    # neuen Ordner erstellen
    md  $subordner -Force | out-null
    # und Datei rein kopieren
    move-item -Path $_.Path -Destination $subordner
}
tio.run
Mitglied: LeaX55
LeaX55 23.04.2021 aktualisiert um 14:30:47 Uhr
Goto Top
Hallo Warranty und danke für die Erklärung.

Regular Expressions ist ja ein komplett eigenes Kapitel. Das muss ich mir alles mal in Ruhe anschauen.

Ich habe noch ein Problem mit dem zweiten Script.
Das ist aber auf meinen Mist gewachsen weil ich dir falsche Info gegeben habe.
Die Textpassage ist schon so:
Bestellnr:
XXXXX

jedoch steht das nicht ganz links. es stehen also noch andere Sachen in diesen 2 Zeilen links und rechts daneben
Text123 Bestellnr: Text456
123456 789012 345678

Deswegen liest er die ganze Zeile unter Bestellnr und da kommt dann natürlich bullshit raus
Mitglied: 148121
148121 23.04.2021 aktualisiert um 15:19:10 Uhr
Goto Top
Kein Thema minimale Anpassung (s.o.) und auch dat lüppt ...
Mitglied: LeaX55
LeaX55 23.04.2021 um 16:09:04 Uhr
Goto Top
irgendwas passt ihm noch nicht.
md : Illegales Zeichen im Pfad.
In C:\Scripte\Archivierung.ps1:12 Zeichen:5
+     md  $subordner -Force | out-null
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (C:\Ordner\|:String) [New-Item], ArgumentException
    + FullyQualifiedErrorId : CreateDirectoryArgumentError,Microsoft.PowerShell.Commands.NewItemCommand
 
move-item : Illegales Zeichen im Pfad.
In C:\Scripte\Archivierung.ps1:14 Zeichen:5
+     move-item -Path $_.Path -Destination $subordner
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Move-Item], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.MoveItemCommand
Mitglied: 148121
148121 23.04.2021 aktualisiert um 16:33:42 Uhr
Goto Top
Steht doch da was ihm nicht passt, lass dir dir Pfad-Variable doch einfach mal anzeigen dann siehst du auch genau welches Zeichen (|) für den Pfad illegal ist ... Mitdenken ... wir kennen ja deine Textdatei nicht!
Wenn du hier nicht exakt spezifizierstwo was steht können wir noch so viele Skripte schreiben bis wir umfallen ...
https://tio.run/##PU29DoIwEN77FDdoqgNE/BucCK4ObA5GDegRSI6W9A41UZ@9NkbZvv ...
Mitglied: LeaX55
LeaX55 27.04.2021 aktualisiert um 10:41:10 Uhr
Goto Top
Hallo warranty,

Zitat von @148121:

...lass dir dir Pfad-Variable doch einfach mal anzeigen dann siehst du auch genau welches Zeichen (|) für den Pfad illegal ist ..
https://tio.run/##PU29DoIwEN77FDdoqgNE/BucCK4ObA5GDegRSI6W9A41UZ@9NkbZvv ...

Das hatte ich gemacht aber dachte dieses Symbol stammt aus dem Code, weil es da auch irgendwo vorkommt.

aber hast vollkommen recht. habe zu wenig Info preisgegeben.

Das Problem ist, dass es 4 verschiedene Kombinationen gibt wie das aussehen kann. Deswegen wars anfangs schwer für mich das zu erklären.
1. Bestellnr: XXXXX
2. Bestellnr:
XXXXX (linksbündig)
3. Bestellnr:
XXXXX (mittendrin)
4. ohne "Bestellnr", nur XXXXX (linksbündig)

Mein Gedanke war, dass wenn ich 1 davon weiss, den Rest alleine hinbiegen kann. Habe meine Kenntnisse wohl überschätzt.

Der 1. Fall funktioniert nun wie es soll.
Das 2. hatte auch funktioniert, seh den Code aber nicht mehr weil du das überarbeitet hattest.
Das 3. geht noch nicht, wegen dem Symbol. Es sieht so aus in der Datei:
1
Über 4. hatten wir noch nicht geredet.
Mitglied: 148121
148121 27.04.2021 aktualisiert um 12:40:49 Uhr
Goto Top
Auf die Extrahierung reduziert, Rest weggelassen ...
Zitat von @LeaX55:
1. Bestellnr: XXXXX
sls 'D:\Ordner\*.txt' -Pattern 'BestellNr:\s*(\d+)' -List | %{$_.Matches.Groups[1].Value}  

2. Bestellnr:
XXXXX (linksbündig)
sls 'D:\Ordner\*.txt' -Pattern 'BestellNr' -List -Context 1 | %{  
    [regex]::Match($_.Context.PostContext,'^(\d+)').Groups[1].Value  
}

3. Bestellnr:
XXXXX (mittendrin)
sls 'D:\Ordner\*.txt' -Pattern 'BestellNr:' -List -Context 1 | %{  
    [regex]::Match($_.Context.PostContext,'\|\s*(\d+)').Groups[1].Value  
}

4. ohne "Bestellnr", nur XXXXX (linksbündig)
Nur eine Kombination aus mehreren Zahlen [0-9] am Anfang einer Zeile? Dann ...
sls 'D:\Ordner\*.txt' -Pattern '^(\d+)' -List | %{$_.Matches.Groups[1].Value}  
Mitglied: LeaX55
LeaX55 27.04.2021 um 17:22:15 Uhr
Goto Top
warranty Du bist einfach der Hammer!
Würde Dir jez gern ein Bierchen ausgeben face-smile

Zitat von @148121:
4. ohne "Bestellnr", nur XXXXX (linksbündig)
Nur eine Kombination aus mehreren Zahlen [0-9] am Anfang einer Zeile? Dann ...
Da steht einfach nur die Bestellnr ohne die Bezeichnung "Bestell-Nr", und zwar immer in Zeile 3 und linksbündig
Mitglied: LeaX55
LeaX55 16.07.2021 aktualisiert um 15:02:38 Uhr
Goto Top
Habe bei Variante 4 noch das Problem, dass der Text aus der ersten Zeile der Textdatei gelesen wird und nicht aus der dritten. Gibts ein Befehl dass der 2 Zeilen noch nach unten springt?

Und bei Variante 3 geht garnix. Bekomme folgende Fehlermeldung:
mkdir : Das Argument kann nicht an den Parameter "Path" gebunden werden, da es NULL ist.  
In C:\MoveFiles.ps1:11 Zeichen:8
+     md $subordner -Force | out-null
+        ~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [mkdir], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,mkdir
 
move-item : Das Argument kann nicht verarbeitet werden, da der Wert des Arguments "destination" NULL ist. Ändern   
Sie den Wert des Arguments "destination" in einen Wert ungleich NULL.  
In C:\MoveFiles.ps1:13 Zeichen:5
+     move-item -Path $_.Path -Destination $subordner
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Move-Item], PSArgumentNullException
    + FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.MoveItemCommand

Der Befehl sieht so aus:
$found = Select-String $quellpfad -Pattern 'Bestellnr' -List -Context 1 | %{  
    # neuen Ordnernamen aus dem regex Submatch extrahieren und mit dem Quell-Ordner zu einem Pfad zusammensetzen
    [regex]::Match($_.Context.PostContext,'\|\s*(\d+)').Groups[1].Value  
    # neuen Ordner erstellen
    md $subordner -Force | out-null
    # und Datei rein kopieren
    move-item -Path $_.Path -Destination $subordner

Grüße
Mitglied: LeaX55
LeaX55 22.07.2021, aktualisiert am 26.07.2021 um 11:07:06 Uhr
Goto Top
Kann mir denn keiner weiterhelfen?