alexander01
Goto Top

Fehler in einem PowerShell-Script zur Umbenennung

Hallo, Ihr habt mir vor einiger Zeit Hilfe bei der Erstellung eines PowerShell-Scriptes zur Umbenennung von Dateinamen gegeben.
Ich merke jetzt, das es bei bestimmten Konstellationen nicht fehlerfrei arbeitet. Kann mir hier jemand behilflich sein?

Ein Unterordner, dessen Namen ein Datum im Format M.T.JJJJ ist, bildet einen Teil des Namens von enthaltenen Dateien, die umbenannt und an eine andere Stelle verschoben werden.
Enthält das übergeordnete Verzeichnis nur einen solchen Unterordner (Name des Unterordners zum Beispiel "5.17.2019") klappt alles. Alle Dateien werden benannt nach dem Schema: [zahl]-jjjj-mm-tt-image[zahl].tif
Es funktioniert nicht mehr, wenn es zwei (oder mehrere?) Unterordner gibt, also z.B.:

5.17.2019
3.28.2022

Das Script (s.u.) benennt alle Dateien mit dem neu formatierten Datum des zweiten Unterordners (hier: 2022-03-28).
Ich habe ermittelt, das es mit dem Befehlsbestandteil $matches[0] zusammenhängt, weiß aber z.b. nicht, was [0] bewirkt.
Freue mich sehr über Hilfe!
Danke!

das Script:

# Pfad bitte anpassen
# benennt Bilder um in [Zahl]-jjjj-mm-tt-Image[xyz]
$root = 'k:\quelle'  
$ziel = 'k:\fertig'  
$batch = 0
# Abfrage aller Ordner der ersten Ebene im Root-Ordner 
Foreach ($DIR in ls $root -Directory ) {
    # alle 5 Ordner anhalten und fragen
    if ($batch % 5 -eq 0){
        Read-Host "`nEnter drücken zum fortfahren für den nächsten Batch an Ordnern"  
    }
    # Unterordner abfragen deren Namen dem Datumsmuster entspricht
    Foreach ($SUB in ls $DIR.FullName -Directory | ?{$_.Name -match '(\d{1,2})\.(\d{1,2})\.(\d{4})'}) {  
        # Datum neu formatieren und an Variable übergeben 
        $d = [datetime]::ParseExact($matches[0],'M.d.yyyy',[cultureinfo]::InvariantCulture).toString('yyyy-MM-dd')  
        # neuen Ordner eine Ebene höher erstellen
        $newfolder = (Join-Path $SUB.Parent.FullName $d)
        md $newfolder -Force | out-null
        # Zähler initialisieren
        $cnt = 1
        # Alle *.tif Dateien des Unterordner "Images" in den neuen Ordner unter neuem Namen verschieben 
        Foreach ($FILE in ls "$($SUB.FullName)\Images" -File -Filter *.tif) {  
            move-item $FILE.Fullname -Destination "$newfolder\$DIR-$d-Image$cnt$($FILE.Extension)" -Verbose  
            move-item "$newfolder\$DIR-$d-Image$cnt$($FILE.Extension)" -Destination $ziel -Verbose  
            $cnt++
        }
        # alten Ordner rekursiv löschen
        del $SUB.FullName -Force -Recurse
    }
    # evt. Steuerdateien löschen
    ls $DIR.Fullname -File | del -Force
    $batch++
    }
    pause
    

Content-ID: 7988452936

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

Printed on: October 11, 2024 at 14:10 o'clock

7907292512
7907292512 Jul 29, 2023 updated at 06:52:04 (UTC)
Goto Top
Moin.
Ersetze $matches[0] durch $SUB.Name

Zur Erklärung, $matches[0] enthählt den Inhalt der zuletzt mit dem -match Operator durchgeführten Regex-Match Operation, das würde hier nur klappen wenn man mit foreach-object in der Pipeline statt einer normalen For-Schleife weiter macht. In diesem Fall ist es aber eine For-Schleife die die Ordner mit dem Datum einmalig ausfiltert und die Pipeline danach zuende ist und deswegen $matches[0] dann immer nur den letzten gefilterten Ordner enthält.
# Pfad bitte anpassen
# benennt Bilder um in [Zahl]-jjjj-mm-tt-Image[xyz]
$root = 'k:\quelle'    
$ziel = 'k:\fertig'    
$batch = 0
# Abfrage aller Ordner der ersten Ebene im Root-Ordner 
Foreach ($DIR in ls $root -Directory ) {
    # alle 5 Ordner anhalten und fragen
    if ($batch % 5 -eq 0){
        Read-Host "`nEnter drücken zum fortfahren für den nächsten Batch an Ordnern"    
    }
    # Unterordner abfragen deren Namen dem Datumsmuster entspricht
    Foreach ($SUB in ls $DIR.FullName -Directory | ?{$_.Name -match '(\d{1,2})\.(\d{1,2})\.(\d{4})'}) {   
        
        # Datum neu formatieren und an Variable übergeben 
        $d = [datetime]::ParseExact($sub.Name,'M.d.yyyy',[cultureinfo]::InvariantCulture).toString('yyyy-MM-dd')    
        # neuen Ordner eine Ebene höher erstellen
        $newfolder = (Join-Path $SUB.Parent.FullName $d)
        md $newfolder -Force | out-null
        # Zähler initialisieren
        $cnt = 1
        # Alle *.tif Dateien des Unterordner "Images" in den neuen Ordner unter neuem Namen verschieben  
        Foreach ($FILE in ls "$($SUB.FullName)\Images" -File -Filter *.tif) {    
            move-item $FILE.Fullname -Destination "$newfolder\$($DIR.Name)-$d-Image$cnt$($FILE.Extension)" -Verbose    
            move-item "$newfolder\$($DIR.Name)-$d-Image$cnt$($FILE.Extension)" -Destination $ziel -Verbose    
            $cnt++
        }
        # alten Ordner rekursiv löschen
        del $SUB.FullName -Force -Recurse
    }
    # evt. Steuerdateien löschen
    ls $DIR.Fullname -File | del -Force
    $batch++
}
pause
Gruß siddius
alexander01
alexander01 Jul 29, 2023 at 07:04:43 (UTC)
Goto Top
Danke für deinen Tip!
Aber egal ob ich $SUB oder $SUB. Name oder $SUB. FullName einsetze, wird nicht die Datumszeichenfolge in die Dateibenennung übernommen.
7907292512
7907292512 Jul 29, 2023 updated at 07:39:38 (UTC)
Goto Top
Lass dir $d doch einfach mal auf der Konsole ausgeben ob das Datum da überhaupt drin steht hier klappt das im Test problemlos.
P.s. PowerShell kannst du auch step für step in der ISE laufen lassen und Breakpoints setzen dann kannst du schön auch selbst debuggen und dir die Variablen einzeln ansehen.

P.s. habe da oben noch etwas korrigiert was im Code nicht ganz stimmte.
alexander01
alexander01 Jul 29, 2023 at 07:45:37 (UTC)
Goto Top
Habe es lösen können:
$SUB.Name enthielt den ganzen String mit Uhrzeit , ich habe den Befehl ParseExacg angepasst auf M.d.yyyy.HH.m.s
Jetzt funktioniert es.
Danke!
7907292512
7907292512 Jul 29, 2023 updated at 07:51:13 (UTC)
Goto Top
Na also, Selbsthilfe ist immer noch der beste Weg 👍. Kann ja hier keiner die Quelldaten sehen 😉.

Siddius