Powershell - Dateien umbenennen


warface

Mitglied
Hallo zusammen,

ich würde gerne automatisiert ca. 30.000 Dateien umbenennen.
leider scheitere ich beim Script an Dateien mit dem gleichen Namen.

Die Dateien sollen so umbenannt werden, dass immer nur die ersten 6 Zeichen übrig bleiben und wenn diese doppelt vorkommen soll ein "_counter" hinten dran kommen.

z.B. aus AAA111 und AAA111CCC sollen AAA111 und AAA111_2 werden.

das ist mein aktuelles Skript, dass Dubletten nicht berücksichtigt.
Code:
$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEU\'
$Files = Get-ChildItem -Path $Path -Recurse -Include *.pdf
foreach ($File in $Files){
    $counter++
    $OldPath = $File.FullName
    $NewName = $OldPath.Substring(37,6) +'.pdf'

    Rename-Item -Path $OldPath -NewName "$Path\$NewName"
}


Mit dem folgenden Script hab ich es versucht, aber da läuft der Counter mit den Dateien mit und wird nicht resetet.
Code:
$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEU\'
$Files = Get-ChildItem -Path $Path -Recurse -Include *.pdf
$Counter = 0
foreach ($File in $Files){
    $counter=1
    $OldPath = $File.FullName
    $NewName = $OldPath.Substring(37,6)

    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $i++)
}

Danke schon mal für die Unterstützung:)
 
Zuletzt bearbeitet:

warface

Mitglied
so ich hab mir was einfallen lassen :)

Code:
#########################################################################################
##Dateien Umbenennen
##Neuer Dateiname = die ersten 6 Zeichen des alten Dateinamen
##Hinter dem Dateinamen wird falls die Datei bereits vorhanden ist mit einem - getrennt ein Counter eingefügt
##Um bei Doubletten Fehler zu vermeiden
#########################################################################################
##aus      ABC123     | ABC123A     | ACD123     | ACD123A     ##
##wird    ABC123     | ABC123-1    | ACD123    | ACD123-1    ##
#########################################################################################

$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEU\'
$Files = Get-ChildItem -Path $Path -Recurse -Include *.pdf
foreach ($File in $Files){
    $counter=1
    $OldPath = $File.FullName
    $Date = get-date -format 'M.d.yyyy HH.mm '
  
    $NewName = $OldPath.Substring(37,6)
  
    Rename-Item -Path $OldPath -NewName "$Path\$NewName.pdf" -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++)
    }

falls jemand eine saubere Lösung hat, dann ich ich die auch gerne :)
 

warface

Mitglied
Da die Daten in einer Excel-Datei verwendet wurden sollte protokolliert werden wie der Name vorher und nachher lautet.
Dazu haben ich folgendes gemacht.

Code:
##########################################################################################
##                                        Dateien Umbenennen                                ##
##                    Neuer Dateiname = die ersten 6 Zeichen des alten Dateinamen            ##
##Hinter dem Dateinamen wird falls die Datei bereits vorhanden ist mit einem - getrennt    ##
##                                        ein Counter eingefügt                            ##
##                Hinter dem Counter wird mit zwei - der alte Namen eingefügt                ##
##                                Um bei Doubletten Fehler zu vermeiden                    ##
##########################################################################################
##    aus      ABC123             | ABC123A             | ACD123             | ACD123A             ##
##    wird    ABC123--ABC123    | ABC123-1--ABC123A    | ACD123--ACD123    | ACD123-1--ACD123A    ##
##########################################################################################
$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEU\'
$Files = Get-ChildItem -Path $Path -Recurse -Include *.pdf
foreach ($File in $Files){
    $counter=1
    $OldPath = $File.FullName
    $OLDName = $OldPath.Substring(37,20)
    $NewName = $OldPath.Substring(37,6)
 
    Rename-Item -Path $OldPath -NewName "$Path\$NewName;$OLDName.pdf" -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1};$OLDName.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1};$OLDName.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1};$OLDName.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1};$OLDName.pdf" -f $Counter++)
    }

Im Anschluss die Dateinamen in eine Datei geschrieben

Code:
##########################################################################################
##        Es wird eine Liste mit den Namen der Dateien in das Verzeichnis geschrieben        ##
##########################################################################################

$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEU\'
Get-ChildItem $Path -recurse -include *.pdf| ForEach-Object { $_.FullName } > $Path\Dateien.csv

Mit der Suchen-Ersetzen-Funktion den Pfad und die Datei Endung rausgelöscht.
In Excel über die Funktion Daten -> Text in Spalten ";" als Trennzeichen hinterlegt damit die Dateiname in zwei Spalten dargestellt werden.
In diesem Zustand können die Daten dann mit einem SVerweis weiter verarbeitet werden.

und mit dem folgenden Skript die Dateiname verarbeitet, dass nur noch die neue Bezeichnung hinterlegt ist

Code:
$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEU\'
$Files = Get-ChildItem -Path $Path -Recurse -Include *.pdf
foreach ($File in $Files){
    $counter=1
    $OldPath = $File.FullName
    $NewName = $OldPath.Substring(37,6)
 
    Rename-Item -Path $OldPath -NewName "$Path\$NewName.pdf" -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++) -ErrorAction SilentlyContinue
    Rename-Item -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.pdf" -f $Counter++)
    }

Beim Umbenennen werden in rot Hinweise angezeigt, diese können ignoriert werden ;-)

Verbesserungsvorschläge sind Willkommen :)
 

HonniCilest

Erfahrenes Mitglied
Mir sträuben sich bei 3 Punkten die Haare:
1. Was ist, wenn sich dein Pfad mal ändert? Dann musst du die 37 im Substring anpassen
2. die feste Anzahl an möglichen Umbenennungen (try & error)
3. Wenn du dein Skript anschließend nochmal drüberlaufen willst, dann benennst du potenziell nochmal alle um

Hier mein Vorschlag, bitte entschuldige, dass ich ein paar Sachen nach dem persönlichen Programmierstil umgebaut habe:
Code:
$Path = 'C:\temp\Tutorials\PDF'
$Files = gci $Path -Recurse -Include '*.pdf' | ?{$_.Name -notmatch "$NewName(-\d+)?\.pdf"} |%{
    $OldPath = $_.FullName
    $NewName = $_.Name.Substring(0,6)
    $counter = (gci $Path -Recurse -Include '*.pdf' | ?{$_.Name -match "$NewName(-\d+)?\.pdf"}).count
    if($counter -eq 0) {
        rni -Path $OldPath -NewName "$Path\$NewName.pdf"
    }
    else {
        rni -Path $OldPath -NewName ("$Path\$NewName-{0:D1}.PDF" -f $Counter++)
    }
}
 

warface

Mitglied
@HonniCilest danke für dein Feedback.
ich beschäftige mich noch nicht ganz so lange mit Powershell und mache sicherlich einige Sachen ziemlich unsauber :)
Daher nehme ich jeden Verbesserungsvorschlag gerne an :)
 

HonniCilest

Erfahrenes Mitglied
Habe gerade gemerkt, dass ich deine Protokollierung vergessen hatte. Sei hier noch hinzugefügt.
Wenn du Fragen dazu hast einfach stellen

Code:
cls
$Path = 'C:\temp\Tutorials\PDF'
$Files = gci $Path -Recurse -Include '*.pdf' | ?{$_.Name -notmatch "$NewName(-\d+)?\.pdf"} |%{
    $OldPath = $_.FullName
    $OldName = $_.Name
    $NewName = $_.Name.Substring(0,6)
    $Counter = (gci $Path -Recurse -Include '*.pdf' | ?{$_.Name -match "$NewName(-\d+)?\.pdf"}).count
    if($Counter -eq 0) {
        $NewName = "$NewName.pdf"
    }
    else {
        $NewName = ("$NewName-{0:D1}.pdf" -f $Counter++)
    }
    ($NewName, $OldName -join ';') >> $Path\Dateien.csv
    rni -Path $OldPath -NewName $NewName
}
 

warface

Mitglied
@HonniCilest danke für die Unterstützung, das sieht doch schon viel besser/übersichtlicher aus als meins und ist mit weniger Arbeit verbunden :)
Leider funktioniert der Befehl bei mir nicht :-(
 

warface

Mitglied
@HonniCilest
hat sich erledigt
hab herausgefunden woran es lag.
Nutzt du ein bestimmtes Tool oder warum kannst du Get-ChildItem und Rename-Item abkürzen?

Code:
$Path = 'C:\AB\Dokumentenablage AP_PP\PDF_NEW\'
$Files = Get-ChildItem $Path -Recurse -Include '*.pdf' | ?{$_.Name -notmatch "$NewName(-\d+)?\.pdf"} |%{
    $OldPath = $_.FullName
    $OldName = $_.Name
    $NewName = $_.Name.Substring(0,6)
    $Counter = (Get-ChildItem $Path -Recurse -Include '*.pdf' | ?{$_.Name -match "$NewName(-\d+)?\.pdf"}).count
    if($Counter -eq 0) {
        $NewName = "$NewName.pdf"
    }
    else {
        $NewName = ("$NewName-{0:D1}.pdf" -f $Counter++)
    }
    ($NewName, $OldName -join ';') >> $Path\Dateien.csv
    Rename-Item -Path $OldPath -NewName $NewName
}
 

HonniCilest

Erfahrenes Mitglied
Ich nutze auch ganz einfach nur Powershell. Ich bin mir nicht bewusst warum Aliase bei dir nicht funktionieren, die Aliase für out-file append (>>) where-object (?{}) und for-each (%{}) funktionieren ja anscheinend auch bei dir. aber ich freue mich, dass es nun zu funktioneiren scheint. Hauptsache du verstehst die Änderungen auch, das finde ich persönlich wichtig.
 

warface

Mitglied
@HonniCilest
die Aliase gehen nun.

Wenn ich bei NewName als Trennzeichen zwischen dem Name und dem Count statt "-" ein "_" verwende, dann geht garnichts mehr.
Hat das einen Grund?

Vielen Dank für deine Hilfe
 
Zuletzt bearbeitet:

HonniCilest

Erfahrenes Mitglied
Wo hast du das Trennzeichen denn alles geändert? Mit dem oben zur Verfügung gestelltem Beispiel müsstest du es an 3 Stellen ändern. Grundsätzlich kann aber ein Grund sein, dass '_' Benennungen von Variablen fortführt, '-' hingegen nicht. Das macht vermutlich in Zeile 11 Probleme, weil dann nach '$NewName_' gesucht wird, welche leer ist, und nicht nach '$NewName'. Du könntest dir das Trennzeichen als eigenes Attribut für bessere Anpassbarkeit ausgliedern.

Also so:
Code:
cls
$Path = 'C:\temp\Tutorials\PDF'
$Trennzeichen = '_'
$Files = gci $Path -Recurse -Include '*.pdf' | ?{$_.Name -notmatch "$NewName($Trennzeichen\d+)?\.pdf"} |%{
    $OldPath = $_.FullName
    $OldName = $_.Name
    $NewName = $_.Name.Substring(0,6)
    $Counter = (gci $Path -Recurse -Include '*.pdf' | ?{$_.Name -match "$NewName($Trennzeichen\d+)?\.pdf"}).count
    if($Counter -eq 0) {
        $NewName = "$NewName.pdf"
    }
    else {
        $NewName = ("$NewName$Trennzeichen{0:D1}.pdf" -f $Counter++)
    }
    ($NewName, $OldName -join ';') >> $Path\Dateien.csv
    rni -Path $OldPath -NewName $NewName
}