Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

[Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

abgdf
Guru
Guru
Beiträge: 3287
Registriert: 13. Apr 2004, 21:15

Re: [Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von abgdf » 22. Mai 2020, 17:46

Wobei ich mir gerade mit dem Satz nicht ganz sicher war. Das Aufrufen eines Programms dürfte ja ein Zusammenspiel von Shell, Prozess-Steuerung ("ps xa") und Programm sein. Kann sein, daß die Shell dem Programm die Arbeit mit dem Unicode abnimmt (vielleicht weiß da jemand anderes Genaueres, das sind ja schon wirklich Interna (daher "Grenze des Machbaren")).
Aber vorsichtig mit Unicode in Dateinamen zu sein, ist in jedem Fall richtig.

Werbung:
Christina
Newbie
Newbie
Beiträge: 38
Registriert: 4. Mär 2019, 13:44

Re: [Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von Christina » 22. Mai 2020, 18:03

Ups! Jetzt habe ich gar nicht gesehen, dass du schon geantwortet hattst.
Ich habe meinen letzten Post nochmal geändert und deine Antwort steht auf der Seite 2.

Gräfin Klara
Hacker
Hacker
Beiträge: 502
Registriert: 23. Jun 2008, 20:51

Re: [Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von Gräfin Klara » 22. Mai 2020, 21:25

abgdf hat geschrieben:
22. Mai 2020, 17:46
Wobei ich mir gerade mit dem Satz nicht ganz sicher war. Das Aufrufen eines Programms dürfte ja ein Zusammenspiel von Shell, Prozess-Steuerung ("ps xa") und Programm sein. Kann sein, daß die Shell dem Programm die Arbeit mit dem Unicode abnimmt (vielleicht weiß da jemand anderes Genaueres, das sind ja schon wirklich Interna (daher "Grenze des Machbaren")).
Aber vorsichtig mit Unicode in Dateinamen zu sein, ist in jedem Fall richtig.
Alles ist Unicode, auch Dateinamen. Unicode selbst ist keine Kodierung sondern eine Norm zur Darstellung von Zeichen,
die Kodierungen zusammenfasst. Diese können sein UTF-32, UTF-16, UTF-8 und ein paar ISO/IEC Normen.
Linux verwendet Zeichen in Unicode mit Kodierung UTF-8, Windows Unicode UTF-16.

Jede Applikation ist selbst für die Kodierung verantwortlich. Fast alle portable Programme verwenden das iconv library (libiconv)
Die Programmierer vom iconv library liefern auch eine Applikation mit dem Namen iconv.
iconv arbeitet mit diesem iconv-library. Mit iconv kannst du herumexperimentieren, strings oder files in alle Richtungen
konvertieren und beobachten, wie es unter Linux oder Windows interpretiert wird.
Man kann sagen, dass das iconv-library der Motor hinter allen Kodierungen und Konvertierungen dieser Art ist.

Gruß
Gräfin Klara

abgdf
Guru
Guru
Beiträge: 3287
Registriert: 13. Apr 2004, 21:15

Re: [Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von abgdf » 23. Mai 2020, 00:03

Gräfin Klara hat geschrieben:
22. Mai 2020, 21:25
Alles ist Unicode, auch Dateinamen. Unicode selbst ist keine Kodierung sondern eine Norm zur Darstellung von Zeichen, die Kodierungen zusammenfasst. Diese können sein UTF-32, UTF-16, UTF-8 und ein paar ISO/IEC Normen.
Linux verwendet Zeichen in Unicode mit Kodierung UTF-8, Windows Unicode UTF-16.
Ah, ok. Ich hatte jetzt UTF-8 synonym zu Unicode verwendet. Das war nicht ganz präzise, Unicode ist der Zeichensatz, UTF-8 (unter Linux) die zugehörige Kodierung. Stimmt schon.

Eigentlich hoffe ich meistens, daß es in Programmen irgendwie gut geht, und beschäftige mich nur damit, wenn es Probleme gibt. ;)
In meinen Python-Programmen hilft meistens:

Code: Alles auswählen

text = text.decode("iso-8859-1")
Wenn nicht, hab' ich ein Problem. Irgendwann muß ich das mal systematisch nachlesen, aber ich hab' immer keine große Lust dazu. :ops: Geht wohl Vielen so. Leidiges Thema.

Christina
Newbie
Newbie
Beiträge: 38
Registriert: 4. Mär 2019, 13:44

Re: bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von Christina » 23. Mai 2020, 09:59

Gräfin Klara hat geschrieben:
22. Mai 2020, 13:41
Alle diese von dir erwähnten Sonderzeichen liegen IMMER im UTF-8 EIN Byte Bereich.
Beispiel '?' = Unicode 0x3F entspricht UTF-8 0x3F.
Unicode 0xFF1F (meines Wissens für UTF-8 wäre das 0x00.ef.bc.9f) sind abseitige Sonderzeichen, die in jedem Fall falsch interpretiert werden würden.
Da die von dir gesuchten Zeichen im EIN Byte UTF-8 liegen, kannst du immer:

Code: Alles auswählen

# VAR=${VAR//[\/\?:]/}      # entnimmt alle diese Sonderzeichen aus VAR
# VAR=${VAR//[\/\?:]/x}     # ersetzt alle diese Sonderzeichen mit einem 'x'
# VAR=${VAR//\?/}           # entnimmt nur '?'
usw.
Ich habe das jetzt mit <FF0F>, <FF1F> und <FF1A> (Unicode 1.1 – Juni 1993) ausprobiert.
Die Reihe mit <FFxx> gibt es auch in UTF-16 und UCS-2.
https://en.wikipedia.org/wiki/UTF-16; https://upload.wikimedia.org/wikipedia/ ... ll_Map.png

Das ist aber im Link-Script nur Spielerei. Das brauche ich hier gar nicht. Ich wollte einfach ein praktisches Beispiel fürs Ersetzen von einzelnen Zeichen in einer Variablen im bash-Script haben.

Code: Alles auswählen

#!/bin/bash

echo -e "Link-Basisname: \c"
read linkbasename
linkbasename=${linkbasename//\///}
linkbasename=${linkbasename//\?/?}
linkbasename=${linkbasename//:/:}
suffix="wav"

nr=1
ls -1 *.$suffix | while read i
do
    ln -s "$i" "$linkbasename-$(printf "%02d" $nr).$suffix"
    echo "$linkbasename-$(printf "%02d" $nr).$suffix -> $i"
    let nr++
done
Nur, wo oder in welchen Fällen würden solche abseitigen Sonderzeichen im Dateinamen Fall falsch interpretiert?
Fällt dir / euch dazu ein Beispiel ein?

Wenn ich im xfce-Terminal die Kodierung von UTF-8 auf ISO-8859-15 umstelle, sind schon die deutschen Umlaute kaputt, klar.

Gräfin Klara
Hacker
Hacker
Beiträge: 502
Registriert: 23. Jun 2008, 20:51

Re: [Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von Gräfin Klara » 24. Mai 2020, 22:04

abgdf hat geschrieben:
23. Mai 2020, 00:03
Geht wohl Vielen so. Leidiges Thema.
So kompliziert ist das nicht.
abgdf hat geschrieben:
23. Mai 2020, 00:03
Eigentlich hoffe ich meistens, daß es in Programmen irgendwie gut geht, und beschäftige mich nur damit, wenn es Probleme gibt. ;)
In meinen Python-Programmen hilft meistens:

Code: Alles auswählen

text = text.decode("iso-8859-1")
Zu deiner Kodierung nach iso-8859-1:
Deine Python Zeile mit x.decode("iso-8859-1") dekodiert den Text in einen
ein Byte code, nämlich in die primäre ASCII Tabelle UND in die extended ASCII Tabelle.
Beide Tabellen sind hier zu sehen:

https://www.ascii-code.com/
Die primäre ASCII Tabelle reicht von 0x00 - 0x7F, die extended Tabelle von 0x80 - 0xFF.

Ein bißchen Geschichte:
Seinerzeit hatte jedes Land mit anderen Zeichen als hierzulande, seine eigene ISO Tabelle.
Alle nach dem Prinzip: ein Zeichen ist ein Byte, Bereich von 0x00 - 0xFF und somit 255 Zeichen maximal.

Das konnte so natürlich nicht weitergehen, z.B. wurde das neue Euro Zeichen mit 0x80 in die extended ASCII Tabelle
hineingequetscht, obwohl es dort überhaupt nicht hinpasst. Die Tabelle war voll, kein Platz mehr vorhanden.

Unicode hat sich dann eine Codierung ausgedacht, die ALLE Zeichen, die auf dieser Welt gebraucht werden,
in einer Tabelle vereint. Begonnen haben sie mit UTF-16, das hatte mit Microsoft zu tun, danach
wurde die UTF-8 Tabelle erstellt.

Wie das Ding funktioniert:
Die 8 in UTF-8 steht nicht für die Zeichenlänge, sondern ist ein Hinweis für den Programmierer, ein Textfile
in 8 Bits zu lesen, also Byte für Byte und zwar ausnahmslos. Weil das so ist, konnte die primäre ASCII Tabelle,
also von 0x00 - 0x7F, 1 zu 1 in die UTF-8 Tabelle übernommen werden. Die extended ASCII Tabelle konnte nicht
integriert werden, Warum? das wirst du bald verstehen

@Christina hat ein Seite über UTF-8 gefunden, wo man das sehen kann.
https://www.utf8-chartable.de/

Ganz links die Angabe zu Unicode ist uninteressant, uns interessiert nur die Spalte UTF-8.
Beginnend von 0x00 - 0x7F findest du die primäre ASCII Tabelle wieder. Ein Byte = ein Zeichen.
Um aber alle Zeichen darstellen zu können, braucht es weit mehr als nur ein Byte je Zeichen.
Nach 0x7F gibt es eine Änderung, dort sieht man 2 Bytes. Wenn der Interpreter - also die Software, die diese
Tabelle in Zeichen übersetzt - auf 0xC2 trifft, dann weiß er, dass er noch ein Byte lesen muß.
Dieses Zeichen ist also 2 Bytes lang, es besteht aus 0xC2 und 0x80. Das Byte 0xC2 nennen wir IB für InformationsByte.

Ein solches IB muß in jedem Fall größer sein als 0x7F, sonst hätte der Interpreter Probleme mit der
ASCII Tabelle am Beginn. Diese IBs ziehen sich durch die gesamte UTF-8 Tabelle und ändern sich natürlich. z.B. fordert 0xE0 zwei
weitere Bytes zu lesen und ab 0xF0 sogar 3 weitere Bytes. Das wäre dann ein Unicode-Zeichen mit einer Größe von 4 Bytes.

Du scheibst:
abgdf hat geschrieben:
23. Mai 2020, 00:03
Wenn nicht, hab' ich ein Problem.
Natürlich gibt es da ein Problem. Alles im primären Bereich der ASCII Tabelle funktioniert trotz deiner iso-8859-1
Kodierung tadellos unter UTF-8. Befindet sich aber z.B. ein Umlaut im Text, dann wird es problematisch. Ein Ä steht laut iso-8859-1
in der extended ASCII Tabelle. Diese ist in UTF-8 aber nicht integriert. Und es wird noch schlimmer.
Das Ä hat nach iso-8859-1 den hex code 0xC4. Der Interpreter findet das 0xC4, interpretiert es als IB und liest
daraufhin auch noch das nächste byte. Das kann im besten Fall ein völlig falsches Zeichen zur Folge haben,
in den meisten Fällen aber kann er damit nichts anfangen und schon gar nicht darstellen. Somit wird nicht nur
etwas falsches angezeigt, es gehen auch Zeichen verloren. Dem Interpreter kann man das nicht vorwerfen, der
will unter Linux UTF-8 und er geht stur danach vor. Welche Kodierung dem File wirklich zugrundeliegt, das
steht ja nicht als Information im File.

UTF-16 funktioniert genau so, nur steht hier die 16 für "Lies immer 16 Bits" also 2 Bytes.
Deshalb würde dein Problem unter Windows, das ja UTF-16 verwendet, noch viel größer sein.
In die UTF-16 Tabelle kann keine ASCII Tabelle integriert werden, UTF-16 kennt kein Zeichen in Bytegröße,

Wie du siehst, ist das recht einfach und wenn du meinen Text verstanden hast, dann hast du auch Unicode-UTF verstanden.

Gruß
Gräfin Klara

abgdf
Guru
Guru
Beiträge: 3287
Registriert: 13. Apr 2004, 21:15

Re: [Gelöst] bash-Script, um viele Dateien automatisch zu verlinken

Beitrag von abgdf » 27. Mai 2020, 01:36

Danke für die Ausführungen!
Gräfin Klara hat geschrieben:
24. Mai 2020, 22:04
Alles im primären Bereich der ASCII Tabelle funktioniert trotz deiner iso-8859-1 Kodierung tadellos unter UTF-8. Befindet sich aber z.B. ein Umlaut im Text, dann wird es problematisch. Ein Ä steht laut iso-8859-1 in der extended ASCII Tabelle. Diese ist in UTF-8 aber nicht integriert. Und es wird noch schlimmer. Das Ä hat nach iso-8859-1 den hex code 0xC4. Der Interpreter findet das 0xC4, interpretiert es als IB und liest daraufhin auch noch das nächste byte. Das kann im besten Fall ein völlig falsches Zeichen zur Folge haben, in den meisten Fällen aber kann er damit nichts anfangen und schon gar nicht darstellen. Somit wird nicht nur
etwas falsches angezeigt, es gehen auch Zeichen verloren. Dem Interpreter kann man das nicht vorwerfen, der will unter Linux UTF-8 und er geht stur danach vor. Welche Kodierung dem File wirklich zugrundeliegt, das steht ja nicht als Information im File.
Also, bei Python 2.7 ist das so: Am Anfang gibt man dem Skript mit, in welcher Kodierung das Skript sein soll. Typischerweise beginnen Python-Skripte daher mit:

Code: Alles auswählen

#!/usr/bin/python
# coding: utf-8
Die zweite Zeile ist trotz "#" am Anfang kein bloßer Kommentar, sondern erfüllt eben diese Funktion.
Laut dem hier
https://stackoverflow.com/questions/499 ... g-encoding
Python 2 reads the source as raw bytes. It only uses the "source encoding" to parse a Unicode literal when it sees one. (It's more complicated than that under the hood but this is the net effect.)
ist es so: Der Datentyp "str" für "normale Strings" ist im Prinzip ASCII. Wenn aber ein Nicht-ASCII-Zeichen im Skript vorkommt, und die "coding"-Zeile oben vorhanden ist, weiß der Python-Interpreter, daß er mit solchen Strings als UTF-8 umgehen soll.
Folgendes funktioniert daher:

Code: Alles auswählen

#!/usr/bin/python
# coding: utf-8
a = "Grüße"
print a
print type(a)
Wenn man explizit Unicode-Strings haben will, kann man ein "u" vor dem String verwenden, also

Code: Alles auswählen

a = u"Hello"
type ist dann "unicode". Aber das ist irgendwie umständlich und sieht nicht cool aus. Die Zeile

Code: Alles auswählen

text = text.decode("iso-8859-1")
wandelt einen String vom Typ "str" nach Typ "unicode".
Wie gesagt ist "str" im Prinzip ASCII, wird manchmal aber auch intern nach UTF-8 (Typ "unicode") gewandelt. Also, dieses geht daher auch:

Code: Alles auswählen

#!/usr/bin/python
# coding: utf-8

a = "Grüße"
print type(a)

b = a.decode("iso-8859-1")
print type(b)
Mit Python 3 stehen ich (und viele andere) auf Kriegsfuß und verwende also bis auf weiteres Python 2.7. Aber zu Python 3.8 lese ich, daß das da dann alles nochmal anders ist, und die grundlegende String-Klasse in UTF-8 ist (wogegen ich im Prinzip auch nichts habe, wenn das gut gemacht ist und im Hintergrund abläuft, ohne den Programmierer damit zu nerven).

Python 2.7 macht das also anders als Python 3.8. Und dann gibt es noch bash, Perl, Java und C/C++, die das auch alle verschieden handhaben dürften. Das ist eher das Problem.

Aufgetreten ist das Encoding-Problem in Python bei mir vor allem bei einem kleinen Texteditor (den ich geschrieben hab'). Da wird also Text aus einem Tkinter-Text-Widget gelesen und soll z.B. in eine Text-Datei geschrieben werden. Wenn in dem Text Umlaute sind, reagiert es (bisher) seltsam. (Auch Eingaben aus einem Tkinter-Entry-Widget sollten überprüft werden.) Vielleicht kann ich das Problem ja jetzt lösen. Mal schauen.

Aber ehrlich gesagt: Wenn selbst in der google-gestützten Python-Welt dafür in Version 2.7 keine dauerhafte Lösung gefunden wurde (und wer weiß, ob die Lösung von Python 3.8 endültig ist?), wie sollen dann so kleine Tools wie awk, grep und sed für das UTF-8-Problem eine Lösung haben? Kann ich mir kaum vorstellen.
Ich vermute, in der Shell dürfte man daher große Probleme bekommen, wenn man Texte mit UTF-8-Zeichen verarbeiten will. Aber das kann hier ja mal gern jemand demonstrieren, der die Shell für sowas einsetzt. Empfehlen würde ich das nicht.

Und auch sonst: Sobald es in der Shell Unklarheiten mit Sonderzeichen oder Dateinamen gibt, wechsele ich gleich zu Perl. In diesen Skriptsprachen ist die Stringverarbeitung einfach viel klarer und leistungsfähiger. Da muß man sich auch kaum Gedanken über Leerzeichen im String oder Expandierungen machen. Dadurch wird einfach alles viel einfacher als in der Shell. Und das eigentliche Problem kann schneller gelöst werden. Werden besondere Shell-Befehle benötigt, kann man die einfach mit "system()" aufrufen.

Antworten