Page 1 of 2

dateinamen öäüß erstzen durch oe ae ue ss

Posted: 23. Nov 2005 13:29
by frank rudolph
Hallo
Ich möchte in einem Pfad mit Unterverzeichnissen alle Umlaute und ß ersetzen durch oe ae ue und ss .
Meine Lösung ist ein kleines Basic Programm (Gambas) welches ein LS in eine Datei macht und die dann Zeilenweise abgearbeitet wird.
sehr sehr langsam ...... :-((

Da gibt es doch bestimmt einen schnellen pearl oder bash script das dieses Problem mit reg ex löst???
Oder gibt es einen ganz anderen Ansatz
Kann mir jemand hefen?

mfg
Frank

Damit sollte es gehen:

Posted: 24. Nov 2005 17:00
by k2

Code: Select all

#!/bin/sh
#
# Umlaute und ß in Dateinamen im aktuellen Verzeichnis ersetzen

for i in *; do
        ii=`echo $i | sed -e's/ä/ae/g' -e's/ö/oe/g' -e's/ü/ue/g' -e's/Ä/Ae/g' -e's/Ö/Oe/g' -e's/Ü/Ue/g' -e's/ß/ss/g'`
if [ $i != $ii ] ; then
        mv $i $ii 
        echo "Datei $i wurde in $ii geändert!"
fi
done
Die sed-Befehle müssen in einer Zeile stehen!

mfG k2

unterverzeichnisse

Posted: 25. Nov 2005 10:43
by frank rudolph
Hallo
Erst mal vielen vielen Dank K2.
Das hilft mir schon mal ne ecke weiter. Habe auch das meiste verstanden :-)

Ich kann bash scripting noch nicht so gut aber ich denke das bei diesem script
die Unterverzeichnisse nicht berücksichtigt werden. (wäre aber wichtig)
Wenn ich auch die Leerzeichen eliminieren möchte würde das mit -e's/ //g' gehen ?

Ich kann nun mit ls eine Datei erstellen mit allen Verzeichnisnamen und dann dein script in eine weitere for schleife packen - die aus der erstellten Datei die Pfad und verzeichnisnamen nimmt und dann die For Schleife für jeden dateinamen durchläuft.
Das wäre die Lösung mit meinen bescheidenen mitteln (kenntnissen)

Wenn noch jemand eine elegantere Lösung kennt - würde mich freuen!!!!
mfg Frank

Posted: 25. Nov 2005 12:17
by Lateralus
Hier eine kleine abgewandelte Form des obigen Scripts, welches sich rekursiv durch die Verzeichnisse arbeitet:

Code: Select all

#!/bin/sh
#
# Umlaute und ß in Dateinamen im aktuellen Verzeichnis ersetzen

# Trennung zwischen Dateinamen ist Newline:
IFS="
"

for i in $(find . -type f); do
        ii=`echo $i | sed -e's/ä/ae/g' -e's/ö/oe/g' -e's/ü/ue/g' -e's/Ä/Ae/g' \
        -e's/Ö/Oe/g' -e's/Ü/Ue/g' -e's/ß/ss/g' -e's/ //g'`
if [ $i != $ii ] ; then
        mv $i $ii
        echo "Datei $i wurde in $ii geändert!"
fi
done
Das müsste funktionieren, wenngleich es Probleme geben könnte, falls die Unterverzeichnisse selbst Umlaute besitzen, da in $i jetzt der gesamte Pfad ab dem aktuellen plus Dateinamen steht.

eine frage noch

Posted: 25. Nov 2005 13:39
by frank rudolph
Vielen Dank Lateralus ......

Zwei Fragen hätte ich noch!
Ich dachte durch das find -type f würde sich das Script sowieso nur auf Dateien und nicht auf Verzeichnisse beziehen.

Wenn ich aus dem f ein d mache würde es dann nur Verzeichnisnamen korrigieren?
Wenn ja dann könnte ich zwei Durchläufe machen ... erst die Verz. dann die Dateien.

Leerzeeichen werden bei diesem Script auch ausgefiltert!!!!

In der ersten Zeile steht IFS=" und das nächste " steht in einer neuen Zeile, soll das so sein?
Die Rekursion ergibt sich automatisch durch den Einsatz von find!!!!

Habe ich alles richtig verstanden ?
Wenn du Lust und Zeit hast kannst du ja nochmal kurz antworten.
mfg
Frank

Posted: 25. Nov 2005 14:40
by Lateralus
Das Problem ist, dass dir dennoch der gesamte Pfad angezeigt wird:

Code: Select all

find / -type f | grep XF86Conf
/etc/X11/XF86Config
und dann werden die Verzeichnisse natürlich mit korrigiert. Das

Code: Select all

IFS="
"
ist korrekt. Dazwischen darf auch nur der Zeilenumbruch stehen, denn genau das ist das Zeichen, was die Dateinamen trennen soll. Andernfalls würde bei der For-Schleife ein Element auch mit Leerzeichen und TAB getrennt.

Das Problem an dem zwei-mal durchlaufen lassen ist dann widerum, dass die Verzeichnisnamen ermittelt werden, bevor die Umbennenung stattfindet. Wenn du also die Verzeichnisse

./Überbleibsel/Ähnliches

hast, erzeugt dein find . -type d folgendes:

Code: Select all

./Überbleibsel
./Überbleibsel/Ähnliches
Dieser werden dann in dieser Reihenfolge umbenannt. Natürlich kann die zweite Umbennenung nicht stattfinden, weil "Überbleibsel" nicht mehr existiert.

Ich bin hier allerdings am Ende meiner Skriptfähigkeit angekommen...

EDIT: vielleicht funktiniert das ganze mit der -exec Funktion von find:

Code: Select all

#!/bin/sh
IFS="
"

find . -exec "newname=$(echo {} | sed -e's/ä/ae/g' -e's/ö/oe/g' -e's/ü/ue/g' -e's/Ä/Ae/g' \
-e's/Ö/Oe/g' -e's/Ü/Ue/g' -e's/ß/ss/g' -e's/ //g'); mv {} $newname" \;

danke

Posted: 25. Nov 2005 15:38
by frank rudolph
Vielen Dank !!!!
Mehr Infos brauche ich auch nicht. Das reicht mir völlig.
Ich habe auch alles verstanden - das bekomme ich dann schon hin.
(denke ich :-) )
mfg
frank

Posted: 26. Nov 2005 12:29
by jochen
Schade, dass ich diesen Thread nicht etwas früher gesehen habe...

Trotzdem gebe ich jetzt noch mal meinen Senf dazu. :)

Code: Select all

#!/bin/bash

find . -iname "*[äöüß]*" -depth -print | \
awk '
{
        match ($0,/.*\//)
        name = substr ($0,RLENGTH+1)
        pfad = substr ($0,1,RLENGTH)
        gsub (/ä/,"ae",name)
        gsub (/ö/,"oe",name)
        gsub (/ü/,"ue",name)
        gsub (/ß/,"ss",name)
        gsub (/Ä/,"Ae",name)
        gsub (/Ö/,"Oe",name)
        gsub (/Ü/,"Ue",name)
        print "mv '\''" $0 "'\'' '\''" pfad name "'\''"
}' | cat
find liefert uns wg. -iname "..." nur Datei-/Verzeichnisnamen, die auch Umlaute enthalten. -depth sorgt dafür, dass erst der Inhalt eines Verzeichnisses aufgelistet wird, bevor das Verzeichnis selbst alleine auftaucht.

Im awk finden wir mittels match() das letzte "/" im Namen und kopieren uns einmal den Pfad der Datei und den Dateinamen selbst heraus. Der Dateiname wird dann von Umlauten befreit (gsub()) und zum Schluss ein mv-Kommando aus dem Originalnamen und dem neuen Namen gebastelt.

Zu Testzwecken schicke ich solche "Shellscripts-on-the-fly" immer durch cat. So erhalte ich die Kommandos, die das Skript erzeugt, ausgegeben. Beispiel:

Code: Select all

jochen@joe$ ./mvumlaut.sh
mv './ärger/häßlich' './ärger/haesslich'
mv './ärger' './aerger'
mv './schlümpf/töricht' './schlümpf/toericht'
mv './schlümpf' './schluempf'
jochen@joe$
WIe man sieht, sorgt -depth dafür, dass ./ärger/häßlich vor ./ärger behandelt wird und dass so der Pfadname seine Gültigkeit nicht verliert.

Wenn einem der Output so gefällt, ersetze man den letzten Bestandteil der Pipeline, also das cat, durch "sh -ev". Die Shell führt die mv-Kommandos dann aus, bricht ab, wenn ein mv-Kommando fehlschlagen sollte (-e) und zeigt, welche Zeilen sie ausführt (-v).

Jochen

wow wasn Brett ....

Posted: 26. Nov 2005 17:05
by frank rudolph
Hi
Das ist ja ein klasse Script.
Habe es nur mal kurz überflogen aber gleich gesehen das ich ja grosse und kleine Umlaute bisher gar nicht berücksuchtigt habe!!!!!
Kann ich das so für Leerzeichen einfach erweitern?
gsub (/ /,"",name)
Ich werde das ganze Script genauestens untersuchen und melde mich auf jeden Fall nochmal.

Vielen Vielen Dank
mfgFrank

Posted: 26. Nov 2005 21:50
by jochen

Code: Select all

gsub (/ /,"",name) 
Ja, genau so. Diese Zeile einfach bei den anderen gsubs einfügen. Die entsprechen übrigens ziemlich exakt dem "s///g" des seds.

Jochen

zwei kleinigkeiten noch

Posted: 26. Nov 2005 22:02
by frank rudolph
Ja super !!!!
Wenn ich die Zeile für die Leereichen einfüge dann werden alle Leezeichen aus Datei und Verzeichnisnamen entfernt die auch einen Umlaut enthalten.

Wenn ich aus allen Datei und Verzeichnisnamen die Leerzeichen entfernen will müsste ich das bestimmt beim find . -iname "*[äöüß]*" -depth .... berücksichtigen oder?
Müsste ich das Leerzeichen dann speziell maskieren? z.B."*[äöüß' ']*" oder so?

Wenn du Tips gibst dann stehen der Code immer in einer hübschen code Box.
Wie füge ich eine solche box in den hilfetext ein?

mfg Frank

Re: zwei kleinigkeiten noch

Posted: 27. Nov 2005 12:07
by jochen
frank rudolph wrote:Wenn ich die Zeile für die Leereichen einfüge dann werden alle Leezeichen aus Datei und Verzeichnisnamen entfernt die auch einen Umlaut enthalten.

Wenn ich aus allen Datei und Verzeichnisnamen die Leerzeichen entfernen will müsste ich das bestimmt beim find . -iname "*[äöüß]*" -depth .... berücksichtigen oder?
*handvordiestirnpatsch* Ja klar! Habe ich total übersehen.
frank rudolph wrote:Müsste ich das Leerzeichen dann speziell maskieren? z.B."*[äöüß' ']*" oder so?
Nein, musst Du nicht. Schmeiß aus Deiner Version die Hochkommata raus, dann ist es korrekt. Denn das Muster ist bereits in Anführungszeichen eingefasst - das untersagt der Shell nicht nur die Dateinamensgenerierung (das soll ja das find-Kommando machen), sondern auch die Auftrennung von Argumenten anhand von Whitespace.
frank rudolph wrote:Wenn du Tips gibst dann stehen der Code immer in einer hübschen code Box.
Wie füge ich eine solche box in den hilfetext ein?
Wenn postest, hast Du über dem Texteingabefald eine Reihe von Buttons für fette, kursive, unterstrichene Schrift, für Zitate, Code, Listen, eingebettete Bilder und URLs. Die fügen aber letztlich nur BBCode in Deinen Text ein - die Hilfe dazu findest Du hier: faq.php?mode=bbcode.

Jochen

Posted: 10. May 2006 10:29
by rdldom

Code: Select all

#!/bin/bash

find . -iname "*[äöüß]*" -depth -print | \
awk '
{
        match ($0,/.*\//)
        name = substr ($0,RLENGTH+1)
        pfad = substr ($0,1,RLENGTH)
        gsub (/ä/,"ae",name)
        gsub (/ö/,"oe",name)
        gsub (/ü/,"ue",name)
        gsub (/ß/,"ss",name)
        gsub (/Ä/,"Ae",name)
        gsub (/Ö/,"Oe",name)
        gsub (/Ü/,"Ue",name)
        print "mv '\''" $0 "'\'' '\''" pfad name "'\''"
}' | cat
Sowas in der Richtung suche ich gerade händeringend. Nur muß ich aus %20 Leerzeichen machen. Aus diesem Grund habe ich das Script abgeändert:

Code: Select all

#!/bin/bash

find . -iname "*[%20]*" -depth -print | \
awk '
{
        match ($0,/.*\//)
        name = substr ($0,RLENGTH+1)
        pfad = substr ($0,1,RLENGTH)
        gsub (/$20/," ",name)
        print "mv '\''" $0 "'\'' '\''" pfad name "'\''"
}' | cat
Leider reicht das wohl nicht. Hier mal eine Ausgabe mit der Option | cat:
mv './savxp/commonappdata/sophos/sophos%20anti-virus' './savxp/commonappdata/sophos/sophos anti-virus'
Das sieht noch sehr gut aus.

Habe ich aber nun mehrere Verzeichnisse mit %20, dann sieht es leider so aus:
mv './savxp/program%20files/sophos/sophos%20anti-virus/module%20retargetable%20folder' './savxp/program%20files/sophos/sophos%20anti-virus/module retargetable folder'

Wie man sehen kann, wird nur der letzte Ordner geändert. Ordner davor werden nicht angerührt.
Nachtrag:
Ich muß die Datei mehrmals starten, dann werden nach und nach die Dateien geändert.
Sicherlich gibt es hier auch eine Lösung, oder? :lol:

Nächste Problem:
Es werden scheinbar auch Daten "versucht" zu ändern, die nichts mit "%20" zu tun haben:
mv './savxp/vdl01.vdb' './savxp/vdl01.vdb'
mv './savxp/vdl02.vdb' './savxp/vdl02.vdb'


Schalte ich das Programm mit "sh -ev" (einfach um schon mal etwas zu ändern), bekomme ich die Meldung:
mv './libeay32.dll' './libeay32.dll'
mv: `./libeay32.dll' and `./libeay32.dll' are the same file

Und das war es auch schon.

Tipps?

Dickes Dankeschön schonmal vorab
Frank

Posted: 10. May 2006 18:53
by klopskuchen

Code: Select all

#/bin/sh
 
ls $1*%20* >/tmp/change.txt
 
while read LINE; do
 
    NEWLINE=`echo $LINE |sed s/%20/' '/`
    echo $NEWLINE 
    #mv $LINE "$NEWLINE"
     
done < /tmp/change.txt
 
rm -rf /tmp/change.txt
 
exit 0;

Aufruf: script_name /absoluter_Pfad_zum Verzeichnis/ (mit abschließendem Schrägstrich).
Wenn die Ausgabe i.O. ist, entferne die Raute vor der Zeile mir dem mv.


MfG, Klopskuchen

Posted: 12. May 2006 5:41
by rdldom
Hallo,
danke dir, wird doch gleich mal am Montag gestet.

Nachtrag:
Getestet. Wenn ich es das Programm ausführe, bekomme ich:

Code: Select all

ls&#58; /group/sophos/Homepage/ESXP/*%20*&#58; No such file or directory
Frank