Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] MAC OS X - Umlaute mit rename ersetzen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] MAC OS X - Umlaute mit rename ersetzen

    Hallo liebe Community,

    ich habe ein riesen Problem.

    Ich lese Dateien mittels opendir und readdir ein Verzeichnis ein.

    PHP-Code:
    function scan($folder) {
        
       
    // Durchsucht den Tagesordner
       
    if ($content opendir($folder)) {
            
           
    // Solange es etwas zu lesen gibt
           
    while (false !== ($file readdir($content))) {

           }
       }

    Dort befinden sich jetzt einige Dateien mit Umlauten (ä,ö,ü,ß,Ä,Ö,Ü)

    Diese möchte ich per rename ersetzen.

    Unter Windows funktioniert das auch ganz einfach:

    PHP-Code:
    function deleteSpecialChars($folder$file) {
        
    // Falls in der Testumgebung (WIN 7), ist die Zeichenkodierung eine andere
    // Jetzt die ANSI-Verzeichniskodierung in UTF-8 umwandeln
    // Speichert erstmal den Pfad und den Dateinamen
    $oldPath "$folder/$file";
    $oldFile "$file";

    // Zwei Arrays fuer str_replace()
    $d1 = array("ä" "ö""ü""ß""Ä""Ö""Ü"" "); 
    $d2 = array("ae" "oe""ue""ss""Ae""Oe""Ue""-");
            
    // Kodiere in UTF-8 Format
    $newFile utf8_encode($oldFile);
            
    // Falls ein Umlaut im Dateinamen ist, ersetze diesen
    if (strstr($newFile"ä") || strstr($newFile"ö") || strstr($newFile"ü") || strstr($newFile"ß") || strstr($newFile"Ä") || strstr($newFile"Ö") || strstr($newFile"Ü") || strstr($file" ")) {

    // Ersetze die Zeichen
    $newFile str_replace($d1$d2$newFile);
                
    // Konkatiniere den neuen Pfad
    $newPath $folder.'/'.$newFile;
                
    //Benennt die Datei um und gibt den Pfad zurueck
    rename($oldPath$newPath);

    Nur unter Mac OS X hat das Script Probleme. Die Abfrage mittels strstr($newFile, "ä") schlägt komplett fehl. Er merkt es einfach nicht.

    Ich tippe mal, dass das an der Zeichenkodierung liegt.

    Bitte helft mir, ich google schon seit Wochen nach einer Lösung.

    Vielen Dank & Grüße

    Michael

  • #2
    so funktioniert es prima:

    PHP-Code:
    //habe mal deine Funktion nur leicht verändert
    function deleteSpecialChars($folder$file) {

        
    $oldPath "$folder/$file";
        
    $oldFile "$file";

        
    $d1 = array("ä" "ö""ü""ß""Ä""Ö""Ü"" "); 
        
    $d2 = array("ae" "oe""ue""ss""Ae""Oe""Ue""-");
            
        
        
    $newFile str_replace($d1$d2$oldFile);
                
        
    $newPath $folder.'/'.$newFile;
        echo 
    "hey".$newPath;
                

        
    rename($oldPath$newPath);
    }
    deleteSpecialChars("test""äböbü.php"); 
    getestet im XCode mit western iso latin1 Codierung.

    Achte auf Schreibrechte!

    Kommentar


    • #3
      So ist das auch kein Problem, weil du ja jetzt ein ISO-Latin kodierten String an die Funktion übergibst.

      Wenn du aber mit readdir eine Datei aus einem Verzeichnis ausliest und den ausgelesenen Dateinamen direkt an die Funktion übergibst, wird er die Umlaute nicht ersetzen, bzw überhaupt finden können mittels strstr().

      Unter windows läuft mein script wie gesagt einwandfrei. Nur der Mac macht Probleme.

      Kommentar


      • #4
        Anmerkung zu Multipostings
        http://phpforum.de/forum/showthread.php?t=267016

        Gruß Jens

        Kommentar


        • #5
          Durchgetestet:

          Und hier:
          http://www.techques.com/question/1-5...-not,-what-is?
          kannst du den Ansatz erkennen.

          ein ä wäre: "a\314\210"

          Ä with A\314\210
          Ö with O\314\210
          Ü with U\314\210
          ä with a\314\210
          ö with o\314\210
          ü with u\314\210

          Erweitere dein Array um die entsprechenden Alternativen.

          Dann funktioniert die Umbennenung einwandfrei.

          Kommentar


          • #6
            Das muß dieser Effekt sein, den man auch regelmäßig in Blogs sieht - dass die Umlaute aus Basisvokal und Diaeresis gebildet wird: http://de.wikipedia.org/wiki/Umlaut#Unicode

            Kommentar


            • #7
              Zitat von dazlious Beitrag anzeigen
              ...
              Unter windows läuft mein script wie gesagt einwandfrei.
              Hier kommt der Einwand: Unter Windows läuft dein Script nur korrekt, wenn die Codepage Win-1252 ("ANSI") eingestellt ist. Unter anderen Codepages finden die PHP-Dateisystemfunktion Einträge mit deutschen Umlauten gar nicht erst. Da wären die kombinierenden diakritische Zeichen, auf die du hier gestoßen bist, das geringere Problem. Soweit mir bekannt, werden die unter Windows-Filesystemen aber "weg-normalisiert". MacOS X dagegen scheint Unicode-Codepoints, die solche Zeichen enthalten, zu zerlegen, zumindest wenn ein Dateisystemeintrag erstellt wird. Bei "fremden" Dateisystemen (wie bspw. FAT32) dagegen, wird auch schon mal deren Normalisierungszustand übernommen (hab ich irgendwo gelesen).

              Wenn die Internationalization-Erweiterung (und ICU) installiert ist, kannst du den String wieder denormalisieren (zu "fully composed"):

              Normalizer::normalize()

              Bedenke aber, dass dein rename()-Ansatz noch eine andere Schwachstelle hat: Du könntest unbeabsichtigt existierende Dateien überschreiben, die zufällig den Zielnamen haben. Das kommt sicher selten vor, macht aber dein Script alles andere als "einwandfrei".

              Nur der Mac macht Probleme.
              Streng genommen macht es MacOS X richtig (die Umwandlung sollte nur konseqent durchgeführt werden): Ein 'ä', das nur aus einem Codepoint besteht, ist ein Anachronismus, der nur aus Gründen der allseits beliebten Abwärtskompatibilität in die Unicode-Tabellen aufgenommen wurde: Damit man hinterher behaupten konnte, dass ISO-Latin-1 eine Teilmenge von Unicode sei.

              Kommentar


              • #8
                Ein 'ä', das nur aus einem Codepoint besteht, ist ein Anachronismus
                Das hätte ich ja gern noch mal erklärt.

                Kommentar


                • #9
                  Zitat von nikosch Beitrag anzeigen
                  Zitat von wirefeasel;
                  Ein 'ä', das nur aus einem Codepoint besteht, ist ein Anachronismus
                  Das hätte ich ja gern noch mal erklärt.
                  Eventuell hier: http://www.unicode.org/faq/char_combmark.html#13

                  Anachronismus ist vielleicht ein zu hartes Wort. Eine Altlast, die wir auf ewig (wegen Abwärtskompatibilität) mitschleifen müssen, trifft es besser.

                  Kommentar


                  • #10
                    Hm, heißt das, ich müsste in einem „Eingabe besteht aus Buchstaben“-Test nicht nur auf General Category[1] L prüfen, sondern zusätzlich noch auf M, wenn ich auch „Buchstaben mit Diakritika“ erwischen will, die nur in NFD vorliegen? Ist das ein realistisches Problem?



                    1: http://www.unicode.org/versions/Unicode6.0.0/ch04.pdf, Tabelle 4-9, Seite 127 (via Wikipedia). L und M fassen etwa in PCRE die Kategorien mit dem entsprechenden Anfangsbuchstaben zusammen (http://www.php.net/manual/en/regexp....ce.unicode.php).

                    Kommentar


                    • #11
                      Vorweg noch was zum (Ursprungs-)Thema: Die schon erwähnte "intl"-Erweiterung besitzt in den neueren Versionen eine Klasse Transliterator, mit der man bspw. deutsche Umlaute nach ASCII wandeln kann. Wenn ich die Anleitung richtig verstanden habe, kann sie sowohl mit "decomposed" als auch mit "precomposed" Zeichen umgehen. Dummerweise macht sie aus 'ä' nur ein 'a' und kein 'ae'. Auch hat die Konvertierung 'Any-ASCII' bei mir nicht funktioniert (es lies sich kein Transliterator-Objekt damit erzeugen), 'Latin-ASCII' dagegen schon.

                      Zitat von mermshaus Beitrag anzeigen
                      Hm, heißt das, ich müsste in einem „Eingabe besteht aus Buchstaben“-Test nicht nur auf General Category... L prüfen, sondern zusätzlich noch auf M, wenn ich auch „Buchstaben mit Diakritika“ erwischen will, die nur in NFD vorliegen?
                      Sieht so aus. Man muss aber aufpassen, diese kombinierenden Zeichen nur mitzuzählen, wenn sie auf Buchstaben folgen. Folgen sie auf ein Non-Breaking-Space (\x{a0}), dann stellen sie sich lediglich selbst dar. Ansonsten scheinen sie quasi "Nicht-Zeichen" zu sein.

                      Zitat von mermshaus Beitrag anzeigen
                      Ist das ein realistisches Problem?
                      Pffft. Der Erbsenzähler in mir sagt: Ja. Immer, wenn Unicode-kodierte Texte aus fremden Quellen kommen, für die du nicht garantieren kannst, dass ...
                      * alle "precomposable" Buchstaben "precomposed" sind oder
                      * nur Buchstaben enthalten sind, die "precomposable" sind.

                      ... oder (einfacher) wenn dieser PCRE anschlägt:
                      PHP-Code:
                      preg_match('/(?<=\p{L})\p{M}/u'$utf8_input); 
                      In der Praxis werden es, wie immer, (fast) alle ignorieren.

                      Andererseits ist das hier ein "Feature"[0] der Dateisystem-Unterstützung von PHP. Da diese unter Windows gar nicht Unicode-fähig ist und unter Unix-(POSIX?)-APIs anscheinend einfach die Pfadnamen weiterleitet, anstatt sie zu vereinheitlichen, darf man sich auf der Anwendungsebene damit herumschlagen.

                      --
                      [0] Fehler darf man ja nicht sagen, das ist alles "by design" ...

                      Kommentar


                      • #12
                        Eventuell hier: http://www.unicode.org/faq/char_combmark.html#13

                        Anachronismus ist vielleicht ein zu hartes Wort. Eine Altlast, die wir auf ewig (wegen Abwärtskompatibilität) mitschleifen müssen, trifft es besser.
                        Ich kann das nicht nachvollziehen. Ein Umlaut ist ein echter Buchstabe, keine besondere Betonung oder so. Unicode wurde dafür geschaffen, alle Zeichen Problemlos abbilden zu können, selbst Ligaturen und Mediävalziffern werden als eigener Unicode geführt. Umlaute aus zwei Zeichen zu kombinieren ist absolut inkonsequent. Jedenfalls für die deutsche Sprache.

                        Kommentar


                        • #13
                          Zitat von nikosch Beitrag anzeigen
                          Ich kann das nicht nachvollziehen. Ein Umlaut ist ein echter Buchstabe, keine besondere Betonung oder so.
                          Nein (deutsche) Umlaute sind gewöhnliche lateinische Buchstaben, versehen mit einem speziellen Zeichen ("Diärese" e.t.c.). Sprachhistorisch sind sie aus Ligaturen, also Kombinationen aus mehreren Buchstaben, entstanden, das 'ä' bspw. aus der ae-Ligatur. Das sie als "gewöhnliche" Buchstaben betrachtet werden, liegt daran, dass man sich als Muttersprachler daran gewöhnt hat.
                          Im asiatischen Raum, stellen deutsche Umlaute und ß regelmäßig eine "besondere Zeichengattung" dar, wie man an kreativ gestalteten Bedienungsanleitung immer wieder sehen kann.

                          Aber wir sollten bei der technische Komponente bleiben ...

                          Unicode wurde dafür geschaffen, alle Zeichen Problemlos abbilden zu können, ...
                          Wenn man Kombinationen aus lateinischen Buchstaben und diese modifizierende Zeichen zulässt, kann man mehr Zeichen aufnehmen, als wenn man für jede gewünschte Kombination einen extra Codepoint reserviert.

                          Mir scheint dass sie den Anspruch "alle Zeichen aufzunehmen" irgendwann aufgegeben und durch das Motto ersetzt: "Wir schauen, bis sich genügend Leute finden, die wollen, dass eine Gruppe von Zeichen aufgenommen werden soll" (siehe Smileys, Emoji usw.). Zugegeben, es ist auch schwer, eine allgemein akzeptierte Definition von "Zeichen" zu erschaffen. Mir fallen da bspw. gerade Verkehrszeichen ein ...

                          ... selbst Ligaturen und Mediävalziffern werden als eigener Unicode geführt.
                          Was unsinnig ist, weil Ligaturen kein Problem der Zeichenkodierung sondern eines der Zeichendarstellung sind. Gleiches gilt für Medieval-Ziffern: Entweder hat ein Font solche Ziffern oder nicht. Etwas anderes wären bspw. die römischen Zahlzeichen.

                          Umlaute aus zwei Zeichen zu kombinieren ist absolut inkonsequent.
                          Erstmal ist das die vorgeschriebene Marschrichtung für die Aufnahme weiterer Zeichen. Das ist verständlich, weil man nicht für alle beliebigen Kombinationen Platz frei halten will oder haben wird. Außerdem macht jedes neue Zeichen mit diakritischem Anbau die Suche und Sortierung komplexer (Die Tabellen für die "Collation-Sequences" werden noch größer).

                          Was die Inkonsequenz betrifft, bin ich deiner Meinung. Aber wenn man sich Überarbeitung für Überarbeitung des Unicode-"Standards" ansieht, ist da konsequente Inkonsequenz das erste, an was man sich gewöhnen muss. Menschliche Schrift(sprache) in Regeln zu pressen zu wollen ist halt kompliziert.

                          Jedenfalls für die deutsche Sprache.
                          Ehrlich gesagt, sind mir deutsche Befindlichkeiten dabei egal. Die waren in ASCII nicht gewahrt und bei den 8-Bit-Zeichensätzen hatten die Deutsch(sprachig)en halt Glück, dass mindestens einer dabei war, der ihren Ansprüchen genügte und auch noch so Sachen wie Groß-Kleinschreibung mit einem Bitflipping erledigt war. Das waren halt die glücklichen 1980-er (und frühen 1990-er) Jahre ...

                          Dass ein Zeichen mehr als ein Byte sein kann, haben wir gelernt, da sollte es nicht schwerfallen auch zu akzeptieren, dass ein Zeichen aus mehr als einen Codepoint zusammengesetzt sein kann.

                          Kommentar


                          • #14
                            Zitat von elise Beitrag anzeigen
                            Durchgetestet:

                            Und hier:
                            http://www.techques.com/question/1-5...-not,-what-is?
                            kannst du den Ansatz erkennen.

                            ein ä wäre: "a\314\210"

                            Ä with A\314\210
                            Ö with O\314\210
                            Ü with U\314\210
                            ä with a\314\210
                            ö with o\314\210
                            ü with u\314\210

                            Erweitere dein Array um die entsprechenden Alternativen.

                            Dann funktioniert die Umbennenung einwandfrei.
                            Ich habe leider heute keinen Mac da, aber ich werde es am Montag testen und mich dann melden, ob es funktioniert hat oder aber wo es noch hakt

                            Kannst du mir noch sagen, wo du die Kodierung gefunden hast (A\314\210, usw)?

                            Brauch nämlich noch ein ß

                            Vielen lieben Dank schon mal für die Antwort, kann morgen kaum abwarten

                            Kommentar


                            • #15
                              Das Eszett hat nichts mit diesem Format zutun.
                              Entweder du nimmst die utf8-encode-Zeile raus und benutzt einfach 'ß', oder eben vorher einen utf8-encode über 'ß'.

                              Kommentar

                              Lädt...
                              X