Dateinamen per Batch Umbennenen (alles hinter 4 stelliger Zahl entfernen)?
Ich habe eine größere Menge Datein in unterschiedlichen Dateiformaten. Jede Datei hat im Dateinamen eine Jahresangabe (ein paar wenige auch zwei). Ich würde gerne den String, also die vierstellige Zahl VON RECHTS suchen und alles inklusive der gesuchten Zahl bis zur Dateiendung entfernen. Letztere muss natürlich bleiben.
Darüber hinaus sollen sämtliche Punkte im Dateinamen (außer der Punkt für die Dateiendung) in Leerzeichen umgewandelt werden. Dafür habe ich bereits einen Code:
@echo off&setlocal
for %%i in (*.*.*) do (
set "neu=%%~ni"
for /f "delims=" %%j in ('call echo "%%neu:.= %%"') do ren "%%~i" "%%~j%%~xi"
)
Ich würde mich sehr über eure Hilfe freuen! Ich komme einfach nicht weiter....
4 Antworten
Folgenden Quelltext anpassen mit dem Pfad und abspeichern als *.vbs Datei.
On Error Resume Next
dim neuName
dim gefunden
dim jahr
dim path
Set fso = CreateObject("Scripting.FileSystemObject")
path = "D:\Users\Edge\Desktop\temp\"
' Hier muss der Pfad nochmal eingetragen werden
Set Folder=fso.GetFolder("D:\Users\Edge\Desktop\temp")
For Each File in Folder.Files
dateiNameExt=right(File.Name,len(File.Name) - InStrRev(File.Name,".")+1)
tempName=left(File.Name,InStrRev(File.Name,".")-1)
jahr = ""
for i = len(tempName) to 1 step - 1
s = mid(tempName,i,1)
if gefunden then
neuName = s & neuName
else
if asc(s)>47 and asc(s)<58 then
jahr = s & jahr
if len(jahr)=4 then
gefunden=true
if mid(tempName,i-1,1)="." then
dotEntfernen=true
end if
end if
end if
end if
next
if not gefunden then
neuName=tempName
else
gefunden=false
end if
if dotEntfernen then
neuName=left(neuName,len(neuName)-1)
dotEntfernen=false
end if
fso.MoveFile path & File.Name, path & neuName & dateiNameExt
neuName=""
Next
stimmt , hast recht 😮🤮 .
Da habe ich mich wohl von dem 2019 als Trenner in den Dateinamensbeispielen leiten lassen. (und meiner VideoSammlung , welche geradezu vor solchen Namen strotzt)
Kannst Du mal sehen wozu Erfahrungsmuster verleiten können.
Sollte jegliche 4 Stellige gesucht werden: *Schnips*
set "regex=\.*[ ]*\b[0-9][0-9][0-9][0-9]\b(?!.*\b[0-9][0-9][0-9][0-9]\b)"
...das wars... 🤩
Edit weil ich übersehen habe, dass du statt . ein Leerzeichen willst.
dim neuName
dim gefunden
dim jahr
dim path
Set fso = CreateObject("Scripting.FileSystemObject")
path = "D:\Users\Edge\Desktop\temp\"
Set Folder=fso.GetFolder("D:\Users\Edge\Desktop\temp")
For Each File in Folder.Files
dateiNameExt=right(File.Name,len(File.Name) - InStrRev(File.Name,".")+1)
tempName=left(File.Name,InStrRev(File.Name,".")-1)
jahr = ""
for i = len(tempName) to 1 step - 1
s = mid(tempName,i,1)
if gefunden then
neuName = s & neuName
else
if asc(s)>47 and asc(s)<58 then
jahr = s & jahr
if len(jahr)=4 then
gefunden=true
if mid(tempName,i-1,1)="." then
dotEntfernen=true
end if
end if
end if
end if
next
if not gefunden then
neuName=tempName
else
gefunden=false
end if
if dotEntfernen then
neuName=left(neuName,len(neuName)-1)
dotEntfernen=false
end if
neuName = Replace(neuName,"."," ")
fso.MoveFile path & File.Name, path & neuName & dateiNameExt
neuName=""
Next
In Sachen Mustererkennung ist unser Gehirn unschlagbar (ein Blick und wir sehen was die Letze Jahreszahl ist und was nur eine 4-stellige Zahl oder sonstwas in der Art ist).
Zugegeben ich musste auch erst überlegen, wie ich eine Entscheidung treffe, was was ist.
Ich habe also folgende Kriterien gesetzt:
- am Rechner relevant sind nur die Jahre 1900 bis 2099 überhaupt in Sachen Dateien .(1. Stelle 1 oder 2, 2. Stelle 0 oder 9, 4. und 4. Stelle 0 bis 9)
- Die Zahl soll ein ganzes Wort sein also nicht innerhalb von Buchstaben oder anderen Zahlen (eine 5-Stellige Zahl ist kein Jahr)
Batch ist alles andere als freundlich, wenn es um die Verarbeitung von Strings geht. Deshalb lasse ich in einem kleinen PowershellScript den String verarbeiten.
Der Reguläre Ausdruck für die die Suche von Rechts nach Links ist sehr selten und eine Logische Umkehrung: suche solange nicht die gefundene Jahreszahl bis zum Ende, dann ist es die Gefunde 😮😬 (total total Gaga). https://www.regular-expressions.info/lookaround.html
funktionstest.cmd
@echo off
chcp 65001 >nul
rem extra fieser DateiName mit vielem was nur aussieht wie ein Jahr
set "FileName1=text.bla. 2025!.text.26.sehr & Komplex.8.text.2011.irgendwas.2019.noch.mehr.Das.ist kein.Jahr-12011.das auch nicht2116.jpg"
set "FileName2=zhfsovho.sfsvfv.tt.2625.ivfbd.fdb.aber dass 2019.das.hier.soll.alles.verschwinden.avi"
set "FileName3=text.bla. 2025.text.26.irgendwatext.test-ÄÖÜ.text.26.irgendwas.8.text.vvfkwgvk.2019.noch.mehr.text.worte.bmp"
rem Suchpattern: negative lookahead, teile am letzen Vorkommen eines ganzen Wortes von 1900 bis 2099 entferne vorangehenden Punkte oder Leerzeichen
set "regex=\.*[ ]*\b[12][09][0-9][0-9]\b(?!.*\b[12][09][0-9][0-9]\b)"
rem Zeichen, welche aus dem Dateinamen entfernt werden sollen &!'
set "rgxSpclChars=[&\!'']"
rem arbeite Dateinamenliste ab....
for %%a in ("%FileName1%","%FileName2%","%FileName3%") do (
rem teile den nackten Namen der Datei an der letzten Jahreszahl (regex) in 2 Teile, wähle den ersten Teil [0] und erstze verbleibende Punkte durch Leerzeichen, entferne einige Sonderzeichen und vereinzelne Leerzeichen
for /f "usebackq tokens=*" %%c in (`powershell "((([regex]'%regex%').split('%%~na',2)[0]) -replace'\.',' ' -replace '%rgxSpclChars%','' -replace'\s+',' ' ).trim()"`) do (
rem zeige Originaldateiname
echo %%~nxa
rem Zeige Neuen
echo %%c%%~xa
echo.
)
)
pause
Das ganze als Droptarget. Du Kannst ca. 100 Dateien auf einmal auf die Batch ziehen ( je nach Pfadlängen ...maximum insgesamt 8100 Zeichen)
@echo off
chcp 65001 >nul
if "%~1"=="" (
echo Zum Umbenennen ziehe die gewünschten Dateien auf "%~nx0" .
timeout 5 >nul
exit /b
)
set "regex=\.*[ ]*\b[12][09][0-9][0-9]\b(?!.*\b[12][09][0-9][0-9]\b)"
set "rgxSpclChars=[&\!'']"
rem arbeite Dateinamenliste ab.... (dateien, welche auf die Batch gezogen wurden)
for %%a in (%*) do (
rem in Subroutine auslagern, spart Eiertanz mit Variablen (siehe Kommentar @Sub)
call :renameIt "%%~fa"
)
pause
exit /b
:renameIt
rem Killer-Dateinamen fixen
rem das Powershellscript vertägt keine SingleQotes (') in Dateinamen!
rem maskieren durch Vedoppeln, dann passts
set "__dummy=%~n1"
set "__dummy=%__dummy:'=''%"
for /f "usebackq tokens=*" %%c in (`powershell "((([regex]'%regex%').split('%__dummy%',2)[0]) -replace'\.',' ' -replace '%rgxSpclChars%','' -replace'\s+',' ' ).trim()"`) do (
set "newName=%%c"
)
rem nur umbenennen, wenn der Name geändert wurde
if "%~nx1" neq "%newName%%~x1" (
echo "%~nx1"
echo "%newName%%~x1"
ren "%~f1" "%newName%%~x1" && (
echo Erfolgreich umbenannt
)||(
echo da hat was nicht geklappt...
)
echo.
) else (
echo nichts zu tun
)
exit /b
...oder mit automatischer Dateisuche. (im Batchordner)
@echo off
chcp 65001 >nul
set "regex=\.*[ ]*\b[12][09][0-9][0-9]\b(?!.*\b[12][09][0-9][0-9]\b)"
set "rgxSpclChars=[&\!'']"
for %%a in (*) do (
call :renameIt "%%~fa"
)
pause
exit /b
:renameIt
set "__dummy=%~n1"
set "__dummy=%__dummy:'=''%"
for /f "usebackq tokens=*" %%c in (`powershell "((([regex]'%regex%').split('%__dummy%',2)[0]) -replace'\.',' ' -replace '%rgxSpclChars%','' -replace'\s+',' ' ).trim()"`) do (set "newName=%%c")
if "%~nx1" neq "%newName%%~x1" (
echo "%~nx1"
echo "%newName%%~x1"
ren "%~f1" "%newName%%~x1" && (
echo Erfolgreich umbenannt
)||(
echo da hat was nicht geklappt...
)
echo.
) else (
echo nichts zu tun
)
Hallo Erzesel,
deine Batch ist super, allerdings benötige ich eine leicht abgewandelte Version und bekomme dein Script leider nicht angepasst. Ich brauche eigentlich fast das gleiche Script wie der Themen Starter, nur dass bei mir die Jahreszahl stehen bleiben soll. Soweit ich verstanden habe kann ich mit deinem Script aber leider nur alles hinter oder Vor der Jahreszahl als Dateinamen setzen. Gibt es da auch eine Andere Lösung? Ich bin leider nirgendwo fündig geworden und würde mich sehr über Hilfe freuen!
Danke und lieben Gruß Marvin
Vielen Dank! Ich habe die letzte Version gewählt weil ich die super flexibel in unterschiedlichen Ordnern verwenden kann. Klappt Super, habe nur das /b hinter exit entfernt.
Wenn ich fragen darf.. Hatte es einen bestimmten Grund, weshalb Du auf das /b verzichtest?
Der Schalter / b sorgt lediglich dafür, das die Console nicht geschlossen wird, wenn eine Batch in einem Consolen-Fenster gestartet wird.
Am Ende einer Subrudine muss dieser sogar verwendet werden.
https://docs.microsoft.com/de-de/windows-server/administration/windows-commands/exit
PS: Wenn Du zufrieden bist, kannst Du unbesorgt die Diversen Buttons und Knöpfe drucken.
😅Sonst bezahlt uns GF nicht...
Ach übrigens...
Wie Du in den Kommentaren von @Geri3d ersehen konntest, hatte ich implizit verstanden, das es um eine Jahreszahl geht, wenn gleich Du dies nicht erwähnt hattest.
Lag ich mit meinem Blick in die Glaskugel richtig ?
Hallo Erzesel,
deine Batch ist super, allerdings benötige ich eine leicht abgewandelte Version und bekomme dein Script leider nicht angepasst. Ich brauche eigentlich fast das gleiche Script wie der Themen Starter, nur dass bei mir die Jahreszahl stehen bleiben soll. Soweit ich verstanden habe kann ich mit deinem Script aber leider nur alles hinter oder Vor der Jahreszahl als Dateinamen setzen. Gibt es da auch eine Andere Lösung? Ich bin leider nirgendwo fündig geworden und würde mich sehr über Hilfe freuen!
Danke und lieben Gruß Marvin
Alles was funktioniert soll mir recht sein! solange ich kein zusätzliches Programm benötige und ich es unter Windows ausführen kann.
Beispiele:
text.bla.text.26.irgendwas.8.text.vvfkwgvk.2019.noch.mehr.text.worte.jpg
zhfsovho.sfsvfv.tt.2625.ivfbd.fdb.vnzk.2019.das.hier.soll.alles.verschwinden.avi
Soll werden zu:
text bla text 26 irgendwas 8 text vvfkwgvk.jpg
zhfsovho sfsvfv tt 2625 ivfbd fdb vnzk.avi
Macht einigermaßen was es soll. ich wäre nicht der Esel, wenn ich nicht ein Aaaaber nachschieben würde.
versuche es mal mit meinem Extremdateinamen:
(ich baue gerne richtig böse Testobjekte,. ich bin fast irre geworden, als mein Script über den Dateinamen " (2) TERRIFYING TALENT! Freaky Magician GIRL Scares Judges & Audience On Asia's Got Talent! - YouTube.url" gestolpert ist und Powerschell nur noch Fehler ausgespuckt hat)
Ich war anfangs auch auf dem Trichter die Zeichen von rechts nach links einzeln abzuscannen. ...aber wozu wenn man den string mit split() an den Punketen zerlegen kann. das geht auch in VBScript und VBS kann auch mit RegEx umgehen (\b[12][09][0-9][0-9]\b sucht in einem String nach genau 4 Zahlen begrenzt durch Zeichen, welche weder Buchstabe noch Zahl sind und mit einem Wert 1900 und 2099 ...6324 oder 0578 sind unmöglich relevante Jahreszahlen ... Ok der Film 2012 könnt evtl betroffen sein, da hoffen wir das da noch etwas rechts steht...)
Allerdings können solche Dateinamen die Irrsinigsten Konstellationen haben und egal wie ich splite es ist möglich, das in einem Feld 2 Jahreszahlen stehen , dann ist bei VBScript immer noch die Linke im Block der Treffer ,denn VBS kan leider nicht mit einem "negative lookahead" von "nicht von Links" (schreibe bewusst nicht "von Rechts") suchen. Ergo bedarf es extra Prüfungen um alle Idiodien zu berücksichtigen...Ich habe schon Pferde vor der Apotheke kotzen sehen...
VBScript wird dies Funktion auch nicht mehr bekommen, da diese Sprache von M$ nicht mehr weiterentwickelt wird (sterbende Sprache)
Letztlich hab ich mich nur für Batch und Powershell entschieden, Da das Dateimanagment relativ simpel ist und Powershell auch komplexe Befehle in einer Kommandozeile ausführen kann.
Wofür Du die Zeilen 17..46 brauchst . (ohne Sonderfälle zu berücksichtigen) erledige ich mit einer Zeile:
Trotzdem freut es mich immer wenn jemand kreativ an eine Lösung herangeht und das ist die Deine auf jeden Fall. Ich käme garnicht mehr ernsthaft auf die Idee einen String "zu Fuß"(Zeichen für Zeichen) zu durchkämmen.
Mit split(string".",-1,1) und Join(StringArray," ") wären alle Punkte Spaces. dazwischen kann man das StringArray von hinten mit RegEx auf eine Jahreszahl durchsuchen.
Das klappt übrigens in allen Sprachen so.
Denke bitte nicht das ich einfach nur herummosere. Ich selbst freue mich über jeden Fehler der in meinen Pogrammen/Scripten gefunden wird, ist es doch ein Grund immer weiter zu lernen. (sonst würde ich heute nicht das können was ich kann)