chakkacor
Goto Top

Powershell - MP3s umbenennen

Hallo,

ich bin komplett neu in die Powershell-Umgebung eingetaucht. Mein Ziel ist es meine MP3s (max. 30 Titel je Ordner) umzubenennen, sodass die Titelnummer am Anfang des Namens steht.

Dazu habe ich auch schon die folgende Funktion im Internet gefunden und Code darunter selbst zusammengebaut. Soweit funktioniert es auch. Das einzige Problem ist, dass er einige Dateien doppelt umbenennt und ich weiß nicht warum. Soll heißen statt "02 - Musik.mp3" steht am Ende "02 - 02 - Musik.mp3" da.

Kann mir hier jemand helfen?

function Add-ExtendedFileProperties{
 <#
     .SYNOPSIS
        Fügt erweiterte Eigenschaften von Dateien an das Objekt in der Pipline hinzu
     .DESCRIPTION
        Extrahiert erweiterte Eigenschaften von Dateien wie z.B. Exif-Daten, Musik- bzw. Filmdetails
     .EXAMPLE 
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties -PropertyExtended "Bildhöhe","Bildbreite","Datenrate" | ft Name,Bildhöhe,Bildbreite,Datenrate  
            Fügt alle nur die Eigenschaften "Bildhöhe","Bildbreite","Datenrate" als zusätzliche Spalten dem Objekt in der Pipline hinzu  
     .EXAMPLE
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties | fl *  
            Fügt alle verfügbaren erweiterten Eigenschaften dem Objekt in der Pipline hinzu
     .PARAMETER PropertyExtended
        Mit diesem Parameter geben sie eine Komma-Separierte Liste von Eigenschaften an welche sie erhalten möchten.
            -PropertyExtended "Bildhöhe","Bildbreite","Bitrate"  
#>
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        $fileItem,
        [String[]] $PropertyExtended = "ALL"  
    )
    begin
    {
        $shellObject = New-Object -Com Shell.Application
        $itemProperties = $null
    }
    process
    {
        if($fileItem.PsIsContainer)
        {
            $fileItem
            return
        }
        $directoryName = $fileItem.DirectoryName
        $filename = $fileItem.Name

        $folderObject = $shellObject.NameSpace($directoryName)
        $item = $folderObject.ParseName($filename)

        if(-not $itemProperties)
        {
            $itemProperties = @{}
            $counter = 0
            $columnName = ""  
            if ($PropertyExtended -eq "ALL"){  
                 #get all properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    if($columnName) { $itemProperties[$counter] = $columnName }
                    $counter++
                }while($columnName)
            }else{
                #get user defined properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    foreach($name in $PropertyExtended){
                        if ($columnName.toLower() -eq $name.toLower()){
                            $itemProperties[$counter] = $columnName
                        }
                    }
                    $counter++
                }while($columnName)
            }
        }

        foreach($itemProperty in $itemProperties.Keys)
        {
            $fileItem | Add-Member NoteProperty $itemProperties[$itemProperty] `
                $folderObject.GetDetailsOf($item, $itemProperty) -ErrorAction `
                SilentlyContinue
        }
        $fileItem
    }
}

$input = Read-Host "Gib den Pfad ein."  
$pfad = $input

$anzahl = Get-ChildItem $pfad -File | Measure-Object | %{$_.Count} #anzahl der Dateien im Ordner bestimmen
$msg = $anzahl
[System.Windows.Forms.MessageBox]::Show($msg,"Titel",0)  
Get-ChildItem $pfad | ForEach-Object{
    $start = $_ | Add-ExtendedFileProperties <#-PropertyE1xtended "Titelnummer"#> | select Titelnummer   
    $ende = $_ | Add-ExtendedFileProperties <#-PropertyE1xtended "Name"#> | select Name   
    [String]$titel1 = $start
    [String]$titel2 = $ende
    
    if($titel1.length -ge 17){ #Länge der Ausgabe bei zwei ziffern = 17
        $laenge = $titel1.length
        $start = $titel1.substring($laenge - 3)
        $nummer = $start.Substring(0,2)
    } #if
        else {#Länge der Ausgabe bei einer ziffer = 16
            $laenge = $titel1.length
            $start = $titel1.substring($laenge - 2) # @Titelnummer:{ entfernen
            $nummer = $start.Substring(0,1) # } entfernen
            $nummer = "0"+$nummer  
        }#Esle
    $laenge = $titel2.Length
    $titel2 = $titel2.Substring($laenge - ($laenge - 7)) # @Name:{ entfernen
    $laenge = $titel2.Length
    $name = $titel2.Substring(0,$laenge - 1) # } entfernen
    $vollername = $nummer+" - "+$name #Zahl und Name zusammenführen  
    <#$msg = $vollername
[System.Windows.Forms.MessageBox]::Show($msg,"Titel",0)#>  
    Rename-Item -Path $pfad\$name -NewName $vollername
} #foreach

Content-Key: 566162

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

Ausgedruckt am: 29.03.2024 um 11:03 Uhr

Mitglied: NordicMike
NordicMike 20.04.2020 um 13:06:42 Uhr
Goto Top
Gut, wir wissen nicht wie die Datei vorher hieß. Aber um der Sache auf die Spur zu kommen bau einfach mal ein Log ein, das dir sämtliche Variablen in den Zwischenschritten anzeigt, dann siehst du wann und warum es doppelt kam.
Mitglied: ChakkaCor
ChakkaCor 20.04.2020 aktualisiert um 13:23:47 Uhr
Goto Top
Wie meinste das mit Log einbauen? Beim Debuggen find ich nichts raus...
Die Anzahl der Dateien gibt er richtig an, läuft aber zum Schluss noch x mal durch...
Mitglied: NordicMike
NordicMike 20.04.2020 um 13:41:22 Uhr
Goto Top
Du lässt dir mitten in deinem Code den Inhalt der Variablen anzeigen. Dann siehst du in welchen Variablen das drinnen steht, was drinnen stehen soll und wo nicht.

Du hast z.B. folgenden Code:

$vollername = $nummer+" - "+$name  
Jetzt lässt du dir den Inhalt von $nummer anzeigen und den Inhalt von $name. Dann siehst du ob in der Variable $nummer eine "02 -" zu viel drinnen steht, oder das "02 -" sogar bereits unter $name drinnen steht, obwohl es da gar nicht mehr sein müsste. So kannst du verfolgen wo der überflüssige String her kommt.
Mitglied: ChakkaCor
ChakkaCor 20.04.2020 um 14:10:31 Uhr
Goto Top
Ich hab das mal so gemacht. er geht alle Titel durch. Und dann sieht es so aus als wenn er nochmal anfängt. Aber eben nicht bei allen.

Das wäre die Ausgabe von Write-Host wenn ich mir Nummer und Name ausgeben lasse:

04 Das...
02 Die...
03 Die ...
05 Dre...
06 Tö...
01 Verd...
04 04 - Das ...
03 03 - Die...
Mitglied: NordicMike
NordicMike 20.04.2020 um 14:57:35 Uhr
Goto Top
Was ist bei "04 04 - Das ..." im $nummer drinnen und was im $name?
Ich vermute, dass in $nummer ein "04 04" drinnen steht und $name in Ordnung ist.
Das kannst du aber nur richtig überprüfen, wenn du bei der Ausgabe ein Trennzeichen oder Erkennungszeichen dazu baust.

Wenn es bestätigt ist, dann musst du weiter oben alle Variablen loggen warum sich $nummer doppelt füllt.
Mitglied: ChakkaCor
ChakkaCor 20.04.2020 um 15:36:34 Uhr
Goto Top
So ist die Ausgabe mit nummer "+mit Namen+" name

05+ mit Namen +Ab...
04+ mit Namen +Blu...
02+ mit Namen +Der ...
08+ mit Namen +Ho...
07+ mit Namen +Mo...
01+ mit Namen +St...
03+ mit Namen +Te...
06+ mit Namen +Ver...
02+ mit Namen +02 - Der ...
08+ mit Namen +08 - Hok...
01+ mit Namen +01 - Stro...

sieht also aus als ob einige Dateien zum zweiten Mal umbenannt werden. eigentlich müsste er wegen foreach nach 8 Files aufhören macht aber in diesem Fall 3 weitere...
Mitglied: NordicMike
NordicMike 20.04.2020 um 16:10:10 Uhr
Goto Top
Lass dir mal $anzahl anzeigen, Zeigt er 8 oder 11 an?
Mitglied: ChakkaCor
ChakkaCor 20.04.2020 um 16:16:24 Uhr
Goto Top
das lass ich schon eine Weile :
8 zeigt er an

Übrigens schon mal vielen vielen Dank für deine Unterstützung - bevor ich es vergesse...
Mitglied: NordicMike
NordicMike 20.04.2020 um 23:21:25 Uhr
Goto Top
Ich habe eine Vermutung:

Wenn Du umbenennst, ließt er die umbenannten Titel neu ein.

Kontrollier das indem du dir die bzw Dateinamen anzeigen lässt, bevor du sie kürzt und umrechnest.
Mitglied: Akeipra
Akeipra 21.04.2020 um 13:11:11 Uhr
Goto Top
Ich kann dir leider bei dem Powershell Problem nicht helfen. Aber um dein Ziel zu erreichen kann ich dir nur dieses Free Tool empfehlen.

https://www.1-4a.com/rename/

Für Hilfe in Powershell, musst du leider auf andere Hilfe hoffen.
Mitglied: erikro
Lösung erikro 21.04.2020 aktualisiert um 14:27:27 Uhr
Goto Top
Moin,

versuche mal statt

Get-ChildItem $pfad | ForEach-Object{

das hier:

$files = Get-ChildItem $pfad 
ForEach($file in $files) {
    # im Folgenden $_ mit $file ersetzen
}

Ich vermute mal, dass Folgendes passiert:

Get-ChildItem liest das Verzeichnis aus und übergibt sofort die ersten Ergebnisse an die Pipe bevor der Befehl vollständig abgearbeitet ist. Nun werden die ersten Dateien umbenannt. Am Ende findet Get-ChildItem die umbenannten Dateien, übergibt sie nochmal an die Pipe und es kommt zu dem falschen Ergebnis.

hth

Erik
Mitglied: ChakkaCor
ChakkaCor 24.04.2020 um 08:01:22 Uhr
Goto Top
Guten Morgen Erik,

Grandios es klappt. Ich habe nur nochmal eine Verständnisfrage:

das $files ist ja nirgends definiert. Ist das eine Variable die Powershell generell definiert hat oder könnte ich sie auch anders benennen?

Vielen Dank

Gruß
Chakka
Mitglied: erikro
erikro 24.04.2020 um 08:42:35 Uhr
Goto Top
Moin,

Zitat von @ChakkaCor:
das $files ist ja nirgends definiert. Ist das eine Variable die Powershell generell definiert hat oder könnte ich sie auch anders benennen?

Doch, die ist definiert. Die erzeuge ich mit

$files = "irgendwas"  

Jetzt steht "irgendwas" in der Variablen. Sie ist eine Stringvariable.


$files = get-childitem


Jetzt stehen die Objekte, die get-childitem zurückgibt, in der Variablen. Sie ist ein Array von Objekten.

Meistens erkennt die PS den richtigen Typ der Variablen von alleine. Manchmal muss man ihn aber explizit angeben. Zum Beispiel, wenn man eine XML-Datei in ein Objekt einlesen möchte.

$notxml = get-content file.xml

schreibt zwar den Inhalt der Datei in die Variable aber eben nicht als XML-Objekt, sondern als String.

[xml]$xml = get-content file.xml

schreibt den Inhalt als XML-Objekt in die Variable.

Letztlich kannst du Variablen benennen, wie Du lustig bist, sofern Du die Regeln einhälst, die für die jeweilige Sprache gelten. Allgemein sollte man sich auf Buchstaben des lateinischen Alphabets, Ziffern und Unterstrich beschränken. Das geht immer. Man sollte sich eine Nomenklatur überlegen und sich dran halten. face-wink Vor allem dann, wenn man mit anderen zusammenarbeitet.

hth

Erik
Mitglied: NordicMike
NordicMike 24.04.2020 aktualisiert um 08:44:15 Uhr
Goto Top
hi
$files =

definiert es automatisch, je nach dem, was du hinter dem "=" rein schiebst.

Edit: In der zwischenzeit war Erik schneller...
Mitglied: ChakkaCor
ChakkaCor 24.04.2020 aktualisiert um 16:15:52 Uhr
Goto Top
Vielen lieben Dank und bleibt gesund. face-smile