Simples Scripting im Alltag: 26 Stunden beim cli.help-Workflow gespart :)
Die Kommandozeile ist bei Nicht-Techies nicht sonderlich beliebt. Und selbst darunter gibt es viele, die ohne Klickibunti nicht wollen oder können. Dabei haben die vielen kleinen Command-Line-Interface-Werkzeuge (CLI) einen riesigen Vorteil: Scripting. Oder anders ausgedrückt: Zusammenarbeit plus Stapelverarbeitung. Darum wäre ein wenig Scriptingfähigkeit auch für viele Office-Bienchen von Nutzen! Heute mal ein Praxisbeispiel aus meinem Arbeitsalltag mit cli.help.
cli.help-Workflow
Einen ausführlichen Beitrag zu cli.help haben wir hier; in aller Kürze: cli.help liefert im Terminal hilfe zu typischen Linux-Tools, ganz einfach über über curl. Hilfe zu chmod bekommt Ihr beispielsweise über curl cli.help/chmod. Mehr auf der GitHub-Seite.
Wenn ich hier nun eine neue Seite schreibe, als Beispiel einfach mal foobar, fallen danach allerlei Aktualisierungen an:
- foobar in readme-Datei eintragen
- foobar in den 5 Listendateien eintragen
- foobar-Inhalt in 3 Dumpdateien anfügen
- HTML-Version foobar.html erstellen
- Link auf foobar.html in browser.html eintragen
- foobar und foobar.html in Git hinzufügen
- Änderungen in git committen
Hier sind also ganze 11 Dateien in 7 Arbeitsschritten beteiligt. Wenn ich nun mal eben fünf neue Tools beschreibe ..., dann ergibt das einen Haufen Arbeit. Und merken muss ich mir ja auch noch, was es alles zu tun gibt. Aber ach, letztlich ist ein Script doch nichts weiter als eine ToDo-Liste, die sich selbst ausführt :O
Einfaches Scripting
Umgebung der Wahl ist die Bash, bei mir sowohl unter Windows in Form der Git Bash, als auch unter diversen Linuxen. Das Schöne bei dieser Aufgabenstellung: Es handelt sich ausschließlich um simple Textverarbeitung. Wenn Ihr einen Workflow wie die obige Liste habt, könnt Ihr einfach schauen, was genau Ihr macht und das in Befehle ummünzen, beispielsweise: Ihr öffnet Datei XY, sucht den letzten Eintrag einer Liste darin und fügt den Namen einer Datei ein - mit offenen Augen sieht sowas ganz fix nach einem Befehl aus. Hilfreich sind ein paar sed-Kenntnisse.
Das folgende Skript clihelpupdate setzt einfach die obige Liste um:
#!/bin/bash
## foobar in readme-Datei eintragen
notepad readme.md && echo Weiter ...
## Schleife, um alle übergebenen Dateien nacheinander auszuführen.
for i in $@; do
## foobar in den 5 Listendateien eintragen
sed -i "/\## Ende.*/i $(basename $i)" meta/{list,liste,befehle,kommandos,programme}
## foobar-Inhalt in 3 Dumpdateien anfügen
cat $i | tee -a meta/{alles,dump,komplett}
## HTML-Version foobar.html erstellen
sed -re '
s/^(.*)/\1\<br\>/g
s/\[..?m//g
s/#{43}//g
s/## *(.*)##/\<H1\>\1\<\/H1\>\ncli\.help ist für den Terminal gedacht:\<br\>\<i\>curl cli\.help\<\/i\>/g
' "$i" | tail -n +20 > html/$(basename $i).html
## Link auf foobar in browser.html eintragen
sed -i "/<\/body>/i <a href=\/$(basename $i)>$(basename $i)<\/a><br />" browser.html
## foobar und foobar.html in Git hinzufügen
## Änderungen in git committen
git add .
git commit -am "$i hinzugefügt; Listen, Dumps und readme.md aktualisiert"
done
Die readme.md muss ich per Hand editieren, öffne sie also in Notepad++ und pausiere das Skript mit && bis ich die Datei wieder schließe.
Die for-Schleife läuft für alle $@, was $1 $2 $3 ... entspricht. Gemeint sind die als Argumente übergebenen Dateien, also etwa foobar1 und foobar2:
./clihelpupdate tools/foobar1 tools/foobar2
Der erste sed-Befehl trägt dann foobar1 und foobar2 in die Programmlisten ein:
sed -i "/\## Ende.*/i $(basename $i)" meta/{list,liste,befehle,kommandos,programme}
Hier wird nach ## Ende gesucht, was einfach am Ende der Liste steht. Über /i wird dann der Dateiname davor eingefügt. Das basename sorgt für den reinen Dateinamen und entfernt die Pfadangabe, hier also /tools.
Es folgt ein einfacher tee-Befehl, der den Inhalt der Dateien foobar1/foobar2 in die Dumps einfügt:
cat $i | tee -a meta/{alles,dump,komplett}
Mit -a fügt tee nur hinzu und über diese schicke geschweifte Klammer gibt tee eben an alle drei Dateien aus. Zusammenarbeit (|) und Stapelverarbeitung ({}) in einer Zeile ;)
HTML-Version
Weiter geht es mit einem umfangreichen sed-Befehl, der aus den für den Terminal gedachten foobar-Dateien eine minimalistische HTML-Version macht. cli.help ist nicht für Browser gedacht, von daher ist das Ergebnis - derzeit noch? - nur eine fehlerbehaftete, aber halbwegs formatierte und lesbare Variante für den Browser. Vielleicht kommt irgendwann etwas Ordentliches, auf die Schnelle genügt es.
## HTML-Version foobar.html erstellen
sed -re '
s/^(.*)/\1\<br\>/g
s/\[..?m//g
s/#{43}//g
s/## *(.*)##/\<H1\>\1\<\/H1\>\ncli\.help ist für den Terminal gedacht:\<br\>\<i\>curl cli\.help\<\/i\>/g
' "$i" | tail -n +20 > html/$(basename $i).html
Der erste Substitute-Befehl (s) macht aus Zeilenumbrüchen HTML-Zeilenumbrüche. Der zweite Befehl entfernt die für die Farben verantwortlichen ANSI-Escape-Sequenzen. Der dritte entfernt die für das Layout genutzten Zeilen mit 43 Rauten. Und der vierte wandelt den internen Titel ## foobar ## in einen HTML-Titel (H1) und fügt ein paar Infos zu cli.help hinzu. Ganz zum Schluss schneidet tail noch den gesamten Header raus und die Datei wird im Verzeichnis html erstellt.
Diese HTML-Datei muss nun in der Datei browser.html verlinkt werden; das ist die Browser-Startseite von cli.help:
## Link auf foobar in browser.html eintragen
sed -i "/<\/body>/i <a href=\/$(basename $i)>$(basename $i)<\/a><br />" browser.html
Gesucht wird nach dem abschließenden Body-Tag, dann davor der HTML-Link plus Umbruch eingefügt.
Abschließen und hochladen
Das Skript hört mit dem Committen auf:
git add .
git commit -am "$i hinzugefügt; Listen, Dumps und readme.md aktualisiert"
So wird für jede neue Datei ein eigener Commit erzeugt, was bei etwaigen Rückgängig-Aktionen nützlich sein kann. Man könnte es aber auch aus der Schleife werfen und allgemeiner committen.
Eigentlich fehlen noch zwei Schritte: Pushen auf GitHub und Hochladen auf cli.help. Das Pushen mache ich aber lieber manuell. Das Hochladen hätte ich mit automatisiert, der Server mag aber kein SCP, mit SFTP hat's nicht auf Anhieb funktioniert, also mache ich das manuell.
Zeiterspartnis/Aufwand
Das Skript ist im Grunde supersimpel, lediglich die regulären Ausdrücke sehen vermutlich etwas lästig aus. Aber RegEx zu lernen lohnt sich garantiert immer! Etwa zum Umbenennen von Dateien. Das Skript benötigt für den Durchlauf natürlich quasi gar keine Zeit, praktisch vielleicht eine Sekunde.
Manuell wären die meisten Dinge (Listen, Dumps, readme, git) in vielleicht drei bis fünf Minuten erledigt, sofern ich mich an alles Schritte erinnern kann (cli.help ist eher ein Nebennbebennebenprojekt, das liegt auch schon mal zwei Wochen brach). Die HTML-Dateien wären rein manuell mit einem grafischen Editor überhaupt nicht sinnvoll zu handeln, das würde jedesmal viele Minuten dauern. Ach Hergott, sagen wir einfach mal alles zusammen würde pro Tool 8 Minuten straffer Arbeit benötigen.
Bislang hat cli.help 87 Seiten und es kommen noch, der Einfachheit halber aber dennoch realistisch geschätzt, 113 Tools dazu, macht 26,67 Stunden. Das Skript ist nebenbei entstanden, mit RegEx-Frickelei und Testdurchläufen hat das vielleicht - ich muss wieder realistisch und vereinfachend schätzen - 1,67 Stunden gedauert. Das Skript wird mir im Laufe der Zeit also rund 25 Stunden reine Arbeitszeit einsparen und die Arbeit 15 mal schneller machen.
Und jetzt stellt Euch vor Ihr seid Office-Bienchen und erledigt immer wieder mal redundante Aufgabe. Oder müsst einfach riesige digitale Papierstapel verarbeiten. Dann sind 25 Stunden verdammt viel wertvolle (Frei-)Zeit - und die springen ja nicht nur einmalig heraus! Scriptingfähige Aufgaben schlummern überall. Apropos: Hier noch allerlei simplere Effizienzkniffe für mehr Kaffeepausen.