bur2000
Goto Top

Dateien nach beliebigen Regeln oder RegExp umbenennen per Batch und sed

Die Anleitung bezieht sich auf Windows.

Ab und zu steht man vor dem Problem dass man eine größere Menge an Dateien nach einem bestimmten Schema umbenennen möchte. In weniger komplexen Fällen geht das einfach mit dem ren Befehl (zB ren *.txt *.doc oder ren ab?.* ab?.txt). Sollen aber zum Beispiel alle Großbuchstaben durch Kleinbuchstaben ersetzt werden oder alle Leerzeichen durch Bindestriche reicht ren nicht mehr aus. Dafür bietet sich das Tool sed in Kombination mit dem FOR Befehl an. Da sed ein sehr mächtiges Tool ist sollten damit im Prinzip fast alle denkbaren Umbenennungen durchführen lassen.

back-to-top1) Wenn nicht vorhanden, sed herunterladen:
sed Download @ sourceforge
sed ist im Prinzip einfach eine sed.exe, ein Kommandozeilen-Tool. Das Setup installiert sed standardmäßig nach %ProgramFiles%\gnuwin32\bin oder %ProgramFiles(x86)%\gnuwin32\bin (für 64bit-Systeme), das Verzeichnis sollte dem Pfad hinzugefügt werden, damit von überall darauf zugegriffen werden kann. Das geht dauerhaft über die Systemsteuerung oder für die jeweilige Eingabeaufforderungssitzung mit path=%path%;%ProgramFiles%\gnuwin32\bin bzw path=%path%;%ProgramFiles(x86)%\gnuwin32\bin.


back-to-top2) Den sed-Befehl verstehen:
Das Umbenennen erledigt sed, man muss das Tool also bedienen können um den Befehl an seine Bedürfnisse anpassen zu können. Hier sollen nur ein paar Standardfälle erläutert werden, wer wirklich tief in das Programm einsteigen will (oder muss) weil er kompliziertere Umbennenungen vornehmen will, wird um ein Tutorial oder das sed-Manual nicht herumkommen.

Die sed-Befehle werden direkt in der Eingabeaufforderung eingegeben. Dazu muss sed.exe im Pfad stehen (s.o.).

Geht es um simples Ersetzen nach dem Schema ersetze alle 'a' durch 'b' sieht der benötigte sed-Befehl so aus:
sed "s:a:b:g"
Das s steht für substitute, also ersetzen. Dann folgt nach dem ersten Doppelpunkt das Zeichen das ersetzt werden soll und nach dem zweiten Doppelpunkt das Zeichen mit dem wir es ersetzen wollen. Danach folgt noch ein Doppelpunkt (wichtig!). Das abschließende g ist optional und bedeutet dass alle a ersetzt werden sollen. Lassen wir es weg, wird nur der erste Treffer ersetzt.

Wer die Befehle direkt ausprobieren will, kann das am besten so machen:
echo Mein Test-Satz| sed "s:e:a:g"
Hier wäre die Ausgabe Main Tast-Satz.

Um alle Leerzeichen durch Unterstriche zu ersetzen schreiben wir also:
sed "s: :_:g"

Damit lassen sich schon viele Probleme lösen, aber es geht noch mehr:
sed "s:[A-Z]:y:g"
[A-Z] findet alle Großbuchstaben und [a-z] alle Kleinbuchstaben. Im obigen Beispiel werden also alle Großbuchstaben durch 'y' ersetzt. Weitere Möglichkeiten sind [0-9] oder [ahg] um 'a', 'h' oder 'g' zu ersetzen oder [i5ef] um alle 'i', '5', 'e' oder 'f' zu ersetzen, usw. Oder man löscht alle Zahlen und Buchstaben mit sed "s:[0-9a-zA-Z]::g" indem man sie durch "nichts" :: ersetzt.

Wenn man jede Zahl durch # ersetzen möchte könnte man sed "s:[0-9]:#:g" versuchen. Leider macht das aus Meine_Zahl_123 ein Mein_Zahl_### und nicht wie vielleicht erwartet ein Meine_Zahl_#. Dazu gibt es \+. Es findet ein oder mehrere des gewünschten Zeichens:
sed "s:[0-9]\+:#:g"
Das macht dann aus 123 hallo 12 ein # hallo #. Das gleiche funktioniert natürlich auch mit [a-z]\+ um kleingeschriebene Wörter zu finden oder [A-Za-z] um alle Wörter zu finden.

Aber was ist, wenn man zB vor jede Zahl ein Nr. setzen möchte? Mit sed "s:[0-9]\+:Nr.:g" kann ich zwar alle Zahlen durch Nr. ersetzen, aber die Zahl selber soll ja erhalten bleiben. Dabei hilft &:
sed "s:[0-9]\+:Nr. &:g"
Das [0-9]\+ findet alle Zahlen (lässt man das \+ weg, würde vor jede Ziffer ein Nr. gesetzt). Nach dem Doppelpunkt folgt Nr. &. Der Trick ist das & - es steht für den zuvor gefundenen String. In unserem Fall also eine beliebig lange Zahl. Aus "123" wird also "Nr. 123" und aus "Hallo 1 und 23" wird "Hallo Nr. 1 und Nr. 23".

Zu guter Letzt noch zwei nützliche Befehle \L und \U. Damit wandelt man Buchstaben in Kleinbuchstaben (Lowercase) bzw Großbuchstaben (Uppercase) um:
sed "s:[A-Z]:\L&:g"
Das [A-Z] findet alle Großbuchstaben und ersetzt sie durch \L&. Das & kennen wir noch, es steht für den zu ersetzenden String der hier aber durch \L in Kleinbuchstaben umgewandelt wurde. Analog geht sed "s:[a-z]:\U&:g".

Man sieht, sed kann sehr viel. Und hier wurde erst ein Teil angerissen, man kann nach Zeilenanfängen suchen, nach Zeilenende, usw. Die gängigsten Probleme sollten aber mit den beschriebenen Befehlen abgedeckt sein. Wer übrigens den Doppelpunkt als Trennzeichen nicht mag, kann jedes beliebige Zeichen benutzen: sed "s;a;b;g". Man muss aber beachten, dass man dann dieses Zeichen nicht ohne weiteres suchen kann. Es muss dann mit dem Backslash escaped werden: sed "s;\;;:;g" benutzt das Semikolon als Trenner und ersetzt alle Semikolons durch Doppelpunkte... Das alles kann man aber auch außer Acht lassen und einfach beim Doppelpunkt als Trenner bleiben, denn der kommt in Dateinamen sowieso nie vor und bietet sich daher an.


back-to-top3) Das wichtigste, der FOR-Befehl:
Bisher können wir zwar Dateinamen mit Hilfe von sed umbauen, aber umbenannt wird noch nichts. Dabei hilft uns der FOR-Befehl:
FOR /f "delims=" %i IN ('dir *.* /b') DO FOR /f %j IN ('echo %i^| sed "s: :_:g"') DO ren "%i" "%j"

Wichtig sind die fettgedruckten Teile. Hier muss man den Befehl an seine Bedürfnisse anpassen. Im vorderen Teil gibt man an welche Dateien umbenannt werden sollen, im Beispiel *.*, also alle im Verzeichnis. Möglich ist natürlich auch *.doc usw. Nur der /b Parameter muss unbedingt erhalten bleiben, damit dir nur den Dateinamen ausgibt. Im hinteren Teil gibt man den benötigten sed-Befehl ein. Im Beispiel werden alle Leerzeichen durch Unterstriche ersetzt.


back-to-top4) Wer wissen möchte was genau der Befehl bewirkt:
Es sind zwei verschachtelte FOR-Schleifen. Die äußere durchläuft alle Dateinamen und speichert den aktuellen Namen in %i. Das "delims=" verhindert dass Dateinamen die Leerzeichen enthalten auseinandergeschnitten werden. Die innere Schleife nimmt das %i und leitet es per echo an sed weiter (das Pipe-Symbol | muss mit ^ escaped werden). Die Ausgabe von sed wird dann in %j gespeichert und mit ren "%i" "j" schließlich die Umbenennung durchgeführt. Eigentlich sind dazu natürlich nicht zwei Schleifen nötig, eine die alle Dateinamen abklappert würde reichen. Leider ist es nicht möglich einfach die Ausgabe eines Programmes in einer Variablen zu speichern. Sonst könnte man sich die zweite Schleife sparen und %j direkt belegen:

FOR ... DO echo %i| sed "s: :_:g" > %j & ren "%i" "%j" wäre eleganter, aber leider nicht machbar.


back-to-top5) Umbenennen mit einer Batch-Datei
Soll der Befehl innerhalb einer Batch-Datei verwendet werden, müssen alle %i und %j durch %%i und %%j ersetzt werden. Es wird vorausgesetzt dass sich die sed.exe im Pfad befindet.

Hier eine Version bei der die umzubenennenden Datei per Drag & Drop auf die Batch-Datei gezogen werden können und dann nach dem zu verwendenden sed-Befehl gefragt wird:
@echo off
set /p sed-command=Bitte sed-Befehl eingeben: 

:LOOP
IF (%1)==() GOTO END

FOR /f "delims=" %%i IN ('dir %1 /b') DO FOR /f %%j IN ('echo %%i^| %sed-command%') DO ren "%%i" "%%j"

SHIFT
GOTO LOOP

:END
set sed-command=

Oder leicht abgewandelt, man wird nach den umzubenennenden Dateien gefragt, die dann in der Form von *.txt oder Kuebelboeck*.mp3 eingegeben werden können:
@echo off
set /p files=Welche Dateien sollen umbenannt werden: 
set /p sed-command=Bitte sed-Befehl eingeben: 

FOR /f "delims=" %i IN ('dir %files% /b') DO FOR /f %j IN ('echo %i^| %sed-command%') DO ren "%i" "%j"

:END
set files=
set sed-command=

Ebenfalls möglich wäre es natürlich die Dateien und den sed-Befehl als Parameter für die Batch-Datei anzugeben.

back-to-top6) Das wars soweit...
Das ganze ist natürlich nicht so intuitiv wie ein GUI-Tool zum Umbenennen, dafür kann es deutlich mehr und ist als Kommandozeilen-Befehl flexibler ohne dabei zu umständlich zu werden. Schließlich bleibt es im Kern bei einer einzelne Zeile. Ich hoffe die Kurzanleitung für sed ist halbwegs verständlich und deckt alle gängigen Fälle ab. Bei Problem gerne hier posten, dann können weitere Beispiele aufgenommen werden.

Je nach Art und Komplexität der Umbenennung sind Tools wie tr oder awk als Alternativen zu sed möglich. Solange das Programm Eingaben über Piping annimmt und nur das Resultat ohne weiteren Text ausgibt kann es ohne Änderungen in den Befehl eingefügt werden.
Kommentar vom Moderator Biber am Jan 18, 2012 um 18:42:54 Uhr
...weil er kompliziertere Umbennenungen vornehmen will
Set /a rgc += 1
#790
Anmerkung: Da aber bei diesem Thema naturgemäß gefühlte 20x das "Umbenennen" durchkliniert werden musste--> mildernde Umstände

Content-Key: 179140

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

Printed on: April 25, 2024 at 12:04 o'clock

Member: Skyemugen
Skyemugen Jan 19, 2012 at 10:12:57 (UTC)
Goto Top
Aloha,

schöne Anleitung, leider werden das die wenigsten 0-8-15-Anwender lesen bzw. kommen dann immer mit den Sätzen muss mit Bordmitteln gehen anund ignorieren selbstverständlich unsere Suchfunktion *fg* und wir haben trotzdem die Arbeit auf dem Tisch *gg*
Achja, die uncodierten Befehlszeilen kannst du auch hilfreich mit ALTGR+7 & ALTGR+0, geht auch in fett, darstellen face-wink

Hmm, das wichtigste: Der FOR-Befehl ... Tutorial zur FOR-Schleife face-wink sollte man dem Leser, der es nicht aus dem FF kann, schon mitgeben.

greetz André

P.S.: Habe mir das jetzt nicht im Detail durchgelesen, weil ich sed auch nicht extra dazu verwenden würde, auch wenn's seine Effizienz hat, aber wo bleibt dann der Spaß? ^__^