lupora
Goto Top

Strings in Dateinamen und Ordnern ersetzen mit Liste

Hallo zusammen,

ich will ein Skript bauen das Strings in Dateinamen und Ordnernamen ersetzt. Input ist eine CSV.

Die CSV sieht so aus:
z.b.
oldstringX, newstringX
oldstringY, newstringY
usw.

Das Skript soll eine Ordnerstruktur rekursiv durchsuchen und überall wo es eine Datei oder Ordner findet der im Dateinamen einen der alten Strings trägt, soll dieser durch den neuen ersetzt werden. Dies gilt für Dateien als auch Ordner.


Die bisherige Struktur schaut so aus:

Elefant
-- Bilder_Januar_Elefant_TollesWetter01.jpg
-- Bilder_Januar_Elefant_TollesWetter02.jpg
-- Bilder_Januar_Elefant_TollesWetter03.jpg

Die CSV dazu wäre

Elefant, Affe
Tiger, Krokodil
Löwe, Schwein

Finale Umsetzung wäre:
Affe
-- Bilder_Januar_Affe_TollesWetter01.jpg
-- Bilder_Januar_Affe_TollesWetter02.jpg
-- Bilder_Januar_Affe_TollesWetter03.jpg

Bisher habe ich in meinem Skript händisch die Werte eingetragen. Ich will das aber über eine Liste lösen, das ist wesentlich effizienter :/

Mein Versuch bisher:
gci $pfad -File -Directory -recurse | Rename-Item -newName { $_.Name -replace "alterSTring", "neuerString") } -verbose

Mit GET Content bekomme ich zwar die Liste und habe mit foreach object rumgespielt, aber ich häng seit fast 2h Stunden dran :/

Hilfe wäre toll face-smile

Content-Key: 621934

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

Printed on: May 3, 2024 at 21:05 o'clock

Member: ricardobohner
ricardobohner Nov 14, 2020 at 15:55:45 (UTC)
Goto Top
Bin Leider noch Anfänger um dir in Powershell zu helfen, aber in Batch währe das so was ähnliches wie das: GIF

@echo off
chcp 1252 > Nul
SetLocal EnableDelayedExpansion

:: Informiere den ordner wo die dateien umbenannt werden sollen:
set Ordner=Mein Ordner

:: Informiere den Pfad zu deiner CSV datei:
set CSV=Meine CSV.csv

For /f "tokens=1,2 usebackq Delims=," %%a in ("Meine CSV.csv") do (  
For /f "delims=" %%c in ('dir /b /s "%Ordner%" ^& echo %Ordner% ^|sort /r ^|find /i "%%a"') do (  
set "Name=%%~nxc"  
set "Name=!Name:%%a=%%b!"  
IF not "!Name!"=="%%~nxc" ren "%%c" "!Name!"  
)
)
exit
Member: Chaos0815
Chaos0815 Nov 15, 2020 at 15:33:41 (UTC)
Goto Top
Wenn du bereit bist, deine CSV-Datei (data.csv) noch mit einer kleinen Überschrift zu versehen, geht es mit diesem PS-Skript:

$BasePath = "C:\users\username\Desktop\Beispiel\"  
$CSV = Import-Csv ($BasePath + "data.csv")  


foreach($file in (Get-ChildItem -Path $BasePath -Recurse -Filter "*.jpg")) {  
    foreach($row in $CSV) {
        if($file.Name -match $row.search) {
            Rename-Item $file.FullName -NewName ($file.Name -replace $row.search, $row.replace) -Verbose
        }
    }
}

Bei mir sah die CSV-Datei dann so aus:
search, replace
Elefant, Affe
Tiger, Krokodil
Löwe, Schwein
Member: Lupora
Lupora Nov 16, 2020 at 14:11:47 (UTC)
Goto Top
Danke für deine Antwort!

Zwei Fragen.

1. Wird nur der String ersetzt oder der ganze Dateiname?
2. Kann man das SCript auch so machen, dass es die Überschriften nicht brauch? Die Listen werden automatisch generiert und ich ahbe keinen Einfluss darauf in der ersten Zeile "search & Replace" einzufügen :/
Member: Chaos0815
Chaos0815 Nov 17, 2020 at 13:28:57 (UTC)
Goto Top
1. Ja, es wird nur der Teilsting ersetzt und nicht der gesamte Dateiname

2. Oh stimmt, habe gerade gesehen es geht auch ohne die Überschriften in der CSV-Datei. Es muss nur die eine Zeile wie folgt ersetzt werden:
$CSV = Import-Csv ($BasePath + "data.csv") -Header "search", "replace"  

Dann brauchst du die Kopfzeile in der Datei nicht mehr.
Member: Lupora
Lupora Nov 18, 2020 at 07:40:50 (UTC)
Goto Top
Wow, mega gut!

Meine letzte Frage: Kann man anstatt Import-CSV auch Import TXT machen? Falls ich keine CSV bekomme sondern TXT ?
Member: Lupora
Lupora Nov 18, 2020 at 09:19:15 (UTC)
Goto Top
Ergänztung: Das Skript ändertn ur Dateinamen um. geht das auch zusötzlich für Ordner?
Member: TK1987
TK1987 Nov 18, 2020 at 20:17:22 (UTC)
Goto Top
Moin,

Zitat von @Lupora:
Meine letzte Frage: Kann man anstatt Import-CSV auch Import TXT machen? Falls ich keine CSV bekomme sondern TXT ?
nein, solange die Textdatei so aufgebaut ist, nutzt du auch für die TXT-Datei import-csv.
Eine Dateiendung spielt letztenendes überhaupt keine Rolle, sondern dient lediglich dazu, dass der Benutzer schneller kapiert wofür eine Datei gedacht ist bzw. welchen Inhalt er erwarten kann. Eine CSV-Datei ist letzten Endes ja auch nur eine gewöhnliche Textdatei, die einem speziellen Dateiaufbau folgt.

Zitat von @Lupora:
Ergänztung: Das Skript ändertn ur Dateinamen um. geht das auch zusötzlich für Ordner?
Das Skript ändert so derzeit nur jpg-Dateien. Wenn du in Zeile 10 -Filter "*.jpg" entfernst, wird alles verarbeitet - also auch Ordner.

Gruß Thomas
Mitglied: 146707
146707 Nov 20, 2020 updated at 18:14:13 (UTC)
Goto Top
Zitat von @TK1987:
Zitat von @Lupora:
Ergänztung: Das Skript ändertn ur Dateinamen um. geht das auch zusötzlich für Ordner?
Das Skript ändert so derzeit nur jpg-Dateien. Wenn du in Zeile 10 -Filter "*.jpg" entfernst, wird alles verarbeitet - also auch Ordner.

Gruß Thomas

Moin.
Das Skript oben fällt einem aber spätestens dann auf die Füße wenn sowohl der Ordner als auch enthaltene Dateien umbenannt werden müssen face-wink. Der Grund: Wird der Ordner vor der enthaltenen Datei umbenannt wird die PS beim nächsten Durchlauf die Datei ja nicht mehr finden da der Ordner ja umbenannt wurde. Deswegen muss man hier die Liste zusätzlich vorher noch nach der Länge des Absoluten Pfades absteigend sortieren damit die enthaltenen Datei vor dem übergeordneten Ordner umbenannt wird und nicht umgekehrt!
Das erreicht man bspw mittels Sort in er Pipeline
...... | sort {$_.Fullname.Length} -Descending | .....

Außerdem wurde dem TO nicht mitgeteilt das hier per Regular-Expressions gesucht wird. Wenn er also in seiner CSV so etwas literal ersetzen würde:
test[ab]
dann würde das Skript sowohl den String testa also auch testb ersetzen. Hier sollte man dann mittels Regex-Escape arbeiten wenn man in der CSV keine Regex-Escaping einsetzen will:
$file.Name -replace [regex]::Escape($row.search), $row.replace

Gruß primal