Hello, Guest the thread was called6.9k times and contains 37 replays

last post from dg5kr at the

Retro Feeling mit Linux Shell

  • Und nochmal eine kleine Verbesserung? Wenn das System keine korrekte termcap-database hat funktionieren die tput Befehle nicht -- hab es jetzt so geändert, dass in dem Fall ein Fallback auf die entsprechenden ANSI Escape-Sequenzen drin ist -- damit passiert natürlich Mist, falls das Terminal die tatsächlich nicht verstehen sollte, aber so funktioniert es z.B. auch auf Windows in der Shell von MSYS2 :)


    edit: damit kann auch terminfo wieder rein, dann fallback auf termcap, dann fallback auf ANSI :)


  • Ok, DAS liegt an der Spezifikation von printf, die tatsächlich vorschreibt, dass Bytes gezählt werden statt Zeichen (und in UTF-8 hat ein ä z.B. 2 Bytes) ... :platsch:


    Workaround für diesen Quatsch:

  • Und nochmal eine kleine Verbesserung? Wenn das System keine korrekte termcap-database hat funktionieren die tput Befehle nicht -- hab es jetzt so geändert, dass in dem Fall ein Fallback auf die entsprechenden ANSI Escape-Sequenzen drin ist -- damit passiert natürlich Mist, falls das Terminal die tatsächlich nicht verstehen sollte, aber so funktioniert es z.B. auch auf Windows in der Shell von MSYS2 :)

    Sehr gut. Das funktioniert auf meinem alten Linux jetzt auch (hatte tput durch eine Null-Funktion ersetzt).

    Ok, DAS liegt an der Spezifikation von printf, die tatsächlich vorschreibt, dass Bytes gezählt werden statt Zeichen (und in UTF-8 hat ein ä z.B. 2 Bytes) ... :platsch:

    So etwas fällt mir immer recht spät auf, da ich hauptsächlich ISO-8859-1/15 verwende. Fein, dass es gelöst ist.

    Bei cut bin ich wirklich von der BSD-Seite her in die Falle getappt -- -w ist nicht portable. Allerdings ist das Verhalten von -d durchaus standardisiert, das fasst keine Trenner zusammen sondern geht von leeren Feldern aus, wird also auch auf Linux nicht zuverlässig funktionieren. Da bleibt nur, statt cut awk und/oder sed zu verwenden.


    realpath ist (POSIX) Standard, und auch bei allen BSDs im Basis-System, es hat aber in alten Versionen der GNU coreutils gefehlt, deshalb kann es auf manchen Linuxen fehlen -- manche legen es auch in ein optionales Paket. Da würde ich trotzdem nichts ändern (Alternative wäre im Script nachimplementieren, und das ist doof...) -- man sollte es auf jedem halbwegs aktuellen Linux system zumindest nachinstallieren können.


    Ein wirklich portierbares Shellscript zu bauen ist erschreckend schwierig :)

    Ich verwendet auch lieber awk um "Worte" zu bekommen, statt mit cut-Optionen herumzuzaubern.


    Die realpath()-Funktion ist im POSIX-Standard. D.h. noch lange nicht, dass es ein entsprechendes Commandline-Programm dazu gibt. ;)

    Diese Kommando ist mir noch nie untergekommen. Wenn man cd+pwd hat, braucht man das auch nicht, ging mir nie ab, in 30 Jahre Unix-Scripting.

    Ich vermeide auch tunlichst alles was erst neu daher kommt.

    Meine Messlatte liegt bei mir historisch bei: muss auf SunOS4 auch laufen. :D

    Zur Hochzeit der OS-Vielfalt hatte ich Apollo Domain mit BSD/SysV, SunOS4 mit BSD-Semantik, SunOS5/Solaris mit SYS5-Semantik und Linux mit einer Mischung aus beidem. Das mündete dann in einem Compatibilty-Include jeweils für csh/sh, das die entsprechenden Tools (z.B. das richtige "awk", z.B. nawk unter SunOS) in Variablen z.B. $AWK abgebildet hat. Was die Optionen angeht, war dann die Schnittmenge davon recht übersichtlich und hat sich auch ganz gut eingeprägt.

    Man hat auch gut von Installer-Scripts lernen können, die früher bei Software-Pakete ein Software-Paket von einem Medium ausgepackt und installiert hat. Das waren sh-Script, die auf allen Plattformen (wo auch die Software verfügbar war) liefen.

    Was ich damit sagen möchte. Adhoc ein portables Script zu schreiben ist sicher schwierig (wenn man wie heute von all dem Schnick-Schnack in Linux-Systemen verwöhnt ist). Wenn man das von Beginn an machen muss, dann wächst man hinein und empfindet das nicht mehr so schlimm oder schwierig. :)

  • Die realpath()-Funktion ist im POSIX-Standard. D.h. noch lange nicht, dass es ein entsprechendes Commandline-Programm dazu gibt. ;)

    Tja, man sollte nichts glauben, was auf Stackoverflow steht* -- da wurde behauptet, das utility (!) sei in POSIX. Ist z.B. hier aber in der Tat nicht zu finden.


    Zum Thema portable: Da würde ich mich (heutzutage) auf POSIX verlassen. Alles andere (solche Absurditäten wie eine csh als Script-Interpreter, oder auch nur ominöse Standardverletzungen und Bugs alter Systeme) ist kaum beherrschbar. Nicht umsonst sehen die von den GNU autotools erstellten configure-scripts aus, wie sie eben aussehen :o


    ----

    *A propos, heute vom Kollegen bekommen: https://twitter.com/Foone/status/1229641258370355200

  • Workaround für diesen Quatsch:

    Was mir noch aufgefallen ist: Symbolic Links werden zusammen mit dem Linkziel als Dateiname ausgegeben. Das Ziel mag ich eigentlich nicht angeführt haben.

    Ich hab in Zeile 34 folgendes noch eingefügt:


    LINE=$(echo "$LINE"|sed -e 's/ -> .*$//')


    Funktioniert im Wesentlichen ganz gut, solange der Dateiname selbst nicht " -> " enthält.

    Alternativ könnte man noch mit echo .* * (als readdir-Ersatz) und dann mit test -d/-l abfragen, ob eine Datei, Verzeichnis oder Link vorliegt.

    Oder besser auf find ausweichen, um auch Dateinamen mit Leerzeichen exakt zu bekommen, z.B. mit

    find . -type d \! -name . -prune -o -name . -o -print0 | xargs -0 -i echo {} | sort | sed -e 's:\./::'

  • Zum Thema portable: Da würde ich mich (heutzutage) auf POSIX verlassen. Alles andere (solche Absurditäten wie eine csh als Script-Interpreter, oder auch nur ominöse Standardverletzungen und Bugs alter Systeme) ist kaum beherrschbar. Nicht umsonst sehen die von den GNU autotools erstellten configure-scripts aus, wie sie eben aussehen :o

    Natürlich, die Zeiten haben sich geändert. POSIX hat es auch früher gegeben, aber auch unterschiedlicher Ausprägung (Versionen). Auch wenn man POSIX-konform ist, bleiben einem die Berücksichtigung von so manchem Quirks bezogen auf bestimmte Plattformen nicht erspart. Wenn das Ziel ist "der Installer muss laufen, egal auf welchem Patch-Stand ein System ist, dann hilft es einem auch nicht zu argumentieren "ja aber, ich hab mein Script POSIX-konform gemacht, wie ihr dann die Software installiert, müsst ihr euch selbst überlegen ...". Kommt halt auf den Anwendungsfall und die Anforderungen.


    Wie gesagt, man kann tatsächlich sehr gut defensive Scripts entwerfen, die auch eine ziemlich gute Abdeckung haben. Man muss das halt nur im Hinterkopf behalten und nicht der Verführung erliegen, jeder neuen GNU-Option nachzuhecheln. ;)

    Ich kenne natürlich viele, die beispielsweise "nur" mit Linux aufgewachsen sind und dafür überhaupt kein Gespür haben. Die Verhalten sich dann so, als wäre Linux das Maß aller Dinge und legen damit ein Verhalten an den Tag, das man sonst bei Herstellern proprietärer Software gerne kritisiert.


    Was ist an csh als Script-Interpreter so absurd? Man kann es wie alles andere beherrschen, wenn man die Fertigkeit dazu hat. :D

  • An find dachte ich auch schon. Das Script ist auf Windows jetzt schon grandios langsam (klar, wohl wegen CreateProcess()) -- noch mehr geforke und gepipe macht es nicht besser :D Auch auf nem richtigen System mit fork() ist es ein bisschen träge. Ich denke mal alle Fallstricke beim Parsen von ls -la habe ich durch, wobei gerade dein Fix für die Symlinks leider nicht 100% sicher ist, trotzdem habe ich das Gefühl, wenn man dieses Tool "perfekt" haben wollte, müsste man wohl eher mit C anfangen. Da hab ich aber gerade keine Lust drauf :)


    Eventuell wäre folgendes sicher, um das Linkziel loszuwerden:

    LINE=$(echo "$LINE" | sed -e 's:\(.*\) -> .*:\1:')

    Durch den greedy match sollte das immer nur ab dem letzten Vorkommen von " -> " abschneiden. ( Das Format mit " -> " ist garantiert: https://pubs.opengroup.org/onl…ilities/ls.html#tag_20_73 )


    edit: ok, wenn das Linkziel selbst " -> " im Namen hat funktioniert das auch nicht ... schätze mal hier ist man mit dem Ansatz, die Ausgabe von ls zu parsen, einfach am Ende.

  • Man muss das halt nur im Hinterkopf behalten und nicht der Verführung erliegen, jeder neuen GNU-Option nachzuhecheln. ;)

    Ich kenne natürlich viele, die beispielsweise "nur" mit Linux aufgewachsen sind und dafür überhaupt kein Gespür haben. Die Verhalten sich dann so, als wäre Linux das Maß aller Dinge und legen damit ein Verhalten an den Tag, das man sonst bei Herstellern proprietärer Software gerne kritisiert.

    Das geht mir selbst auf den Keks ... ich paketiere ab und zu Software für FreeBSD und musste da schon öfter mal "bashismen" fixen ;)

    Was ist an csh als Script-Interpreter so absurd? Man kann es wie alles andere beherrschen, wenn man die Fertigkeit dazu hat. :D

    Dazu mal ne GANZ alte Quelle: http://harmful.cat-v.org/software/csh

    Da ist sicher vieles nicht mehr aktuell, aber es geht ja schon mit der Frage los: wo ist eigentlich der Standard für C-Shells, auf den man sich verlassen kann?

  • edit: ok, wenn das Linkziel selbst " -> " im Namen hat funktioniert das auch nicht ... schätze mal hier ist man mit dem Ansatz, die Ausgabe von ls zu parsen, einfach am Ende.

    ls -Q setzt die Filenamen in Double-Quotes. Damit könnte man dann den Filenamen exakt erkennen. Ein " im Namen wird dann als \"

    quotiert dargestellt.

    Oder mit ls -1sFQ den Typ als einzelnes Class-Zeichen am Ende setzen. Aber die Size-Information ist dann nicht in Bytes, sondern in Blocks (was ja eigentlich eher dem C64-Stil entspricht ;) )

    Der Name ist in Double-Quotes und eventuell von einem "@", "*", "/", "|" (Link, Exec, Dir., Pipe) gefolgt und kann eindeutig erkannt werden.

  • ls -Q setzt die Filenamen in Double-Quotes.

    Nur leider steht das hier auch nicht drin: https://pubs.opengroup.org/onl…ilities/ls.html#tag_20_73


    Das GNU ls (jedenfalls die Version in meinem MSYS2) setzt Namen mit Leerzeichen in single-quotes, aber auch dieses Verhalten steht leider nicht im Standard. Vielleicht passiert das ja auch nur bei Ausgabe auf ein Terminal, habe ich nicht getestet... Rein aus Neugierde teste ich bei Gelegenheit mal, ob das FreeBSD ls das auch tut :)

  • Dazu mal ne GANZ alte Quelle: http://harmful.cat-v.org/software/csh

    Da ist sicher vieles nicht mehr aktuell, aber es geht ja schon mit der Frage los: wo ist eigentlich der Standard für C-Shells, auf den man sich verlassen kann?

    Ja, das ist das übliche (berechtigte) Gejammere über die Csh. Als Csh-Programmierer kenn man diese Probleme und umschifft sie. Das macht es zwar nicht schöner, aber es gibt Gründe und Konstellationen Csh dennoch zu verwenden.

    Zu der Zeit 1996, nach 5 Jahren Csh-Programmierung, wäre ich zum gleichen Schluss gekommen. Wenn man sich die Fertigkeit mal angeeignet hat, dann tut es ja nicht mehr weh, damit zu leben. Aber bei jeder Gelegenheit ziehe ich mittlerweile sh/bash einer csh vor bzw. spreche diese Empfehlung jederzeit aus. Also wenn man etwas Neues beginnt, sollte man bei sh/bash bleiben. Da finden sich auch leichter Leute, die das beherrschen. Ich komme mir als Csh-Programmierer eh schon wie ein Dinosaurier vor (älter sind da wohl nur noch die FORTRAN- und COBOL-Programmierer, die den Status unumstritten innehaben). :D

  • Ja, wahrscheinlich sollten wir das hier abbrechen ... zum Script würde ich sagen, die letzte Version, die ich hier gepostet habe, ist sicher hinreichend portierbar und funktioniert für das meiste wie erwartet, man könnte noch JeeK s Ergänzung dazunehmen um keine Ziele von Symlinks zu sehen (was ja in 99% aller Fälle auch problemlos funktionieren würde).


    Ein "Weg vorwärts" könnte höchstens noch sein, ls durch find zu ersetzen -- aber vielleicht mag da ja auch dg5kr noch ein Wörtchen mitreden :D


    Einige Postings sollten wohl eher in einem Thread über "portable (POSIX) shell scripting" stehen -- sind wir mit dem Thema durch, und, falls nicht, interessiert das hier noch mehr als 2 Leute? Wahrscheinlich nicht ...

  • Ein "Weg vorwärts" könnte höchstens noch sein, ls durch find zu ersetzen -- aber vielleicht mag da ja auch dg5kr noch ein Wörtchen mitreden :D

    Also ich kriege das Grinsen nicht mehr aus dem Gesicht. Was ich für Kräfte freigesetzt habe mit einem kleinen Mittagspausen Script....

    Ihr habe euch ordnentlich ins Zeug gelegt und das letzte gepostete diR benutze ich schon fast lieber als ein ls -al :thumbsup:

  • Zu der Idee, das in C zu bauen, hab ich (weil man Windows ja eigentlich nie außen vor lässt) n bisschen in der Microsoft Doku geblättert.


    hier hab ich aufgehört (wtf? 8|)

    Ich finde ein würdiges Gegenstück zum Shellscript wäre ein CMD Shellscript (diR.cmd). Kein Powershell, das wäre zu einfach.