bash
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| bash [2025-08-31 13:29:14] – [bc] manfred | bash [2025-08-31 22:08:18] (aktuell) – [Zahlen von eine Basis in eine andere Basis umrechnen] manfred | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== bash (Bourne SHell / Bourne-Again SHell) ====== | ||
| + | |||
| + | In jedem Unix-Ähnlichen System findet sich die klassische //Bourne SHell// unter /// | ||
| + | |||
| + | Aus diesem Grund scripte ich mit Vorliebe für diese Shell. Dann laufen die Scripte nicht nur auf Linux, sondern auch auf NetBSD, FreeBSD, Solaris, AIX und anderen Unix-Ähnlichen Betriebssystemen. | ||
| + | |||
| + | [[http:// | ||
| + | |||
| + | [[http:// | ||
| + | |||
| + | |||
| + | ===== farbige Textausgabe (24bit Farben) ===== | ||
| + | |||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | ESC[38; | ||
| + | ESC[48; | ||
| + | ESC[0m | ||
| + | |||
| + | * '' | ||
| + | * 1. Paramter: '' | ||
| + | * 2. Paramter: '' | ||
| + | * 3/4/5. Paramter: rot/ | ||
| + | |||
| + | |||
| + | ==== Beispiel um Syntax zu vereinfachen ==== | ||
| + | |||
| + | Variablen: | ||
| + | * TEXT: Text der printf übergeben wird | ||
| + | * XY | ||
| + | * X: Vordergrund (F) oder Hintergrund (B) | ||
| + | * Y: rot (R), grün (G) oder blau (B) | ||
| + | |||
| + | Umgebungsvariable als Shortcut | ||
| + | PRINT_COLOR=' | ||
| + | |||
| + | Nutzung | ||
| + | TEXT=" | ||
| + | TEXT=" | ||
| + | TEXT=" | ||
| + | TEXT=" | ||
| + | TEXT=" | ||
| + | |||
| + | **Achtung: Die Semikolon (;) sind wichtig!** | ||
| + | |||
| + | |||
| + | ===== Bash - Pattern ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | |||
| + | ==== Klammererweiterung ==== | ||
| + | |||
| + | Dann gibt es die Klammererweiterung (Brace-Expansion). Klammererweiterung passt technisch nicht in die Kategorie der Muster, ist aber ähnlich. | ||
| + | Globs werden nur auf tatsächliche Dateinamen erweitert, aber Klammererweiterungen werden auf jede mögliche Permutation ihres Inhalts erweitert. | ||
| + | So funktionieren sie: | ||
| + | $ echo th{e,a}n | ||
| + | then than | ||
| + | $ echo {/ | ||
| + | / | ||
| + | $ echo {1..9} | ||
| + | 1 2 3 4 5 6 7 8 9 | ||
| + | $ echo {0,1}{0..9} | ||
| + | 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | ||
| + | |||
| + | Die Klammererweiterung wird durch eine Liste von Wörtern ersetzt, genau wie ein Glob. Diese Wörter sind jedoch nicht unbedingt Dateinamen, und sie sind nicht sortiert (als wären sie vorher gekommen). | ||
| + | |||
| + | __Die Klammererweiterung erfolgt vor der Dateinamenerweiterung.__ Im zweiten echo-Befehl oben haben wir eine Kombination aus Klammererweiterung und Globs verwendet. Die Klammererweiterung geht zuerst und wir erhalten: | ||
| + | $ echo / | ||
| + | |||
| + | Nach der Klammererweiterung werden die Globs erweitert und wir erhalten als Endergebnis die Dateinamen. | ||
| + | |||
| + | Klammererweiterungen können nur verwendet werden, um Wortlisten zu generieren. Sie können nicht für den Mustervergleich verwendet werden. | ||
| + | |||
| + | Es gibt einige interessante und nicht sehr intuitive Unterschiede zwischen den Bereichen in Zeichenklassen wie '' | ||
| + | $ echo {b..Y} | ||
| + | b a ` _ ^ ] [ Z Y | ||
| + | |||
| + | |||
| + | ===== Feldtrennzeichen - Delimiter (IFS) ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | anzeigen | ||
| + | cat -etv | ||
| + | |||
| + | |||
| + | ===== Remote Procedure Call - RPC ===== | ||
| + | |||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | |||
| + | ===== automatische Ersetzung im Dateinamen ===== | ||
| + | |||
| + | Hier wird die Dateiendung " | ||
| + | for Datei in *.mts; do mv -v " | ||
| + | ffmpeg -i 00001.text 00001.txt | ||
| + | |||
| + | |||
| + | |||
| + | ===== Optionen ===== | ||
| + | |||
| + | > man bash | ||
| + | Laut Doku werden bei " | ||
| + | Laut Doku werden bei " | ||
| + | In meinen Test konnte ich bei beiden nur einer Erweiterung mit Leerzeichen erkennen. | ||
| + | |||
| + | __Ich konnte keinen Unterschied zwischen ''" | ||
| + | |||
| + | <file bash / | ||
| + | #!/bin/bash | ||
| + | |||
| + | echo '# 1: " | ||
| + | echo " | ||
| + | echo '# 2: $*' | ||
| + | echo $* | ||
| + | |||
| + | echo '# 3: " | ||
| + | echo " | ||
| + | echo '# 4: $@' | ||
| + | echo $@ | ||
| + | |||
| + | echo '# 5: " | ||
| + | echo " | ||
| + | echo '# 6: $#' | ||
| + | echo $# | ||
| + | echo '# 7: #' | ||
| + | |||
| + | echo " | ||
| + | echo " | ||
| + | echo " | ||
| + | echo " | ||
| + | echo " | ||
| + | echo "# | ||
| + | echo $1 | ||
| + | echo $2 | ||
| + | echo $3 | ||
| + | echo $4 | ||
| + | echo $5 | ||
| + | </ | ||
| + | > / | ||
| + | # 1: " | ||
| + | 1 2 3 4 5 6 7 8 | ||
| + | # 2: $* | ||
| + | 1 2 3 4 5 6 7 8 | ||
| + | # 3: " | ||
| + | 1 2 3 4 5 6 7 8 | ||
| + | # 4: $@ | ||
| + | 1 2 3 4 5 6 7 8 | ||
| + | # 5: " | ||
| + | 5 | ||
| + | # 6: $# | ||
| + | 5 | ||
| + | # 7: # | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 6 7 8 | ||
| + | # | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 6 7 8 | ||
| + | |||
| + | |||
| + | ===== Funktionen ===== | ||
| + | |||
| + | In der Bash wird eine Funktion fast so gebaut wie in " | ||
| + | |||
| + | Alle Variablen, die außerhalb der Funktion definiert wurden, | ||
| + | sind auch in der Funktion verwendbar: | ||
| + | # | ||
| + | VARIABLE=" | ||
| + | funktionx() | ||
| + | { | ||
| + | echo " | ||
| + | } | ||
| + | funktionx | ||
| + | |||
| + | Wird eine Skript-Datei mit z.B. zwei Parametern aufgerufen, | ||
| + | dann sind bekanntlich diese vier übergebenen Parameter in der Datei | ||
| + | als "// | ||
| + | |||
| + | Genauso verhält es sich mit den Parametern bei den Funktionen: | ||
| + | # | ||
| + | NACHNAME=" | ||
| + | VORNAME=" | ||
| + | funktiony() | ||
| + | { | ||
| + | echo " | ||
| + | FARBE=' | ||
| + | ELEMENT=' | ||
| + | VORNAME=' | ||
| + | NACHNAME=' | ||
| + | " | ||
| + | } | ||
| + | funktiony schwarze erde ${VORNAME} ${NACHNAME} | ||
| + | |||
| + | Hier sind die Parameter, die der Funktion übergeben werden, | ||
| + | innerhalb der Funktion auch wieder als “$1“, “$2“, ... verwendbar. | ||
| + | |||
| + | ===== Entscheidungen ===== | ||
| + | |||
| + | Bei Entscheideidungen muss man unterscheiden, | ||
| + | |||
| + | Die " | ||
| + | in soeinem Fall muss man dann auf AWK zurückgreifen. | ||
| + | |||
| + | |||
| + | ==== BASH ==== | ||
| + | |||
| + | if [ " | ||
| + | GR=klein | ||
| + | elif [ " | ||
| + | GR=mittel | ||
| + | elif [ " | ||
| + | GR=gross | ||
| + | else | ||
| + | GR=" | ||
| + | fi | ||
| + | | ||
| + | echo " | ||
| + | |||
| + | |||
| + | ==== AWK ==== | ||
| + | |||
| + | # echo " | ||
| + | 1.5=mittel | ||
| + | |||
| + | # echo " | ||
| + | 2 | ||
| + | |||
| + | |||
| + | ===== Zählschleifen ===== | ||
| + | |||
| + | |||
| + | ==== BASH ==== | ||
| + | |||
| + | Unter Linux ist die //GNU Bourne-Again SHell// unter /// | ||
| + | sie ist in erster Linie für die Konsolenarbeit verbesert worden. | ||
| + | So verfühgt sie im Gegensatz zur //Bourne SHell// über eine Historie. | ||
| + | |||
| + | Die //GNU Bourne-Again SHell// verfühgt aber auch über zusätzliche Funktionen, die für die Arbeit mit Scripten wichtig sind. | ||
| + | |||
| + | Zum Beispiel funktioniert der kleine Time-Out-Zähler nur in der //GNU Bourne-Again SHell//, nicht jedoch in der //Bourne SHell//: | ||
| + | |||
| + | # | ||
| + | WARTEZEIT=" | ||
| + | while [ ! -e /tmp/datei ] | ||
| + | do | ||
| + | sleep 1 | ||
| + | if [ " | ||
| + | WARTEZEIT=$((WARTEZEIT - 1)) | ||
| + | else | ||
| + | touch /tmp/datei | ||
| + | fi | ||
| + | done | ||
| + | |||
| + | die folgenden beiden Zählschleifen funktionieren nur mit einer '' | ||
| + | |||
| + | > i=0 ; while ((" | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 | ||
| + | 6 | ||
| + | 7 | ||
| + | 8 | ||
| + | 9 | ||
| + | 10 | ||
| + | |||
| + | > i=10;while ((" | ||
| + | 10 | ||
| + | 9 | ||
| + | 8 | ||
| + | 7 | ||
| + | 6 | ||
| + | 5 | ||
| + | 4 | ||
| + | 3 | ||
| + | 2 | ||
| + | 1 | ||
| + | |||
| + | |||
| + | === sh === | ||
| + | |||
| + | Für die //Bourne SHell// muss das Kommando //bc// das rechnen im Script übernehmen: | ||
| + | |||
| + | #!/bin/sh | ||
| + | WARTEZEIT=" | ||
| + | while [ ! -e /tmp/datei ] | ||
| + | do | ||
| + | sleep 1 | ||
| + | if [ " | ||
| + | WARTEZEIT=" | ||
| + | else | ||
| + | touch /tmp/datei | ||
| + | fi | ||
| + | done | ||
| + | |||
| + | |||
| + | oder das Kommando //awk//: | ||
| + | |||
| + | #!/bin/sh | ||
| + | WARTEZEIT=" | ||
| + | while [ ! -e /tmp/datei ] | ||
| + | do | ||
| + | sleep 1 | ||
| + | if [ " | ||
| + | WARTEZEIT=" | ||
| + | else | ||
| + | touch /tmp/datei | ||
| + | fi | ||
| + | done | ||
| + | |||
| + | |||
| + | === bc === | ||
| + | |||
| + | natürlicher Logarithmus aus 5: | ||
| + | > echo " | ||
| + | 1.60943791243410037460 | ||
| + | |||
| + | natürlicher Logarithmus aus 20: | ||
| + | > echo " | ||
| + | 2.99573227355399099343 | ||
| + | |||
| + | dezimaler Logarithmus 1000: | ||
| + | > echo " | ||
| + | 3.00000000000000000000 | ||
| + | |||
| + | binärer Logarithmus aus 8: | ||
| + | > echo " | ||
| + | 3.00000000000000000002 | ||
| + | |||
| + | > echo "a=1; b=2; c=3; print \" | ||
| + | a=1; b=2; c=3; print " | ||
| + | | ||
| + | > echo "a=1; b=2; c=3; print \" | ||
| + | a=1 b=2 c=3 | ||
| + | Summe:6 | ||
| + | |||
| + | |||
| + | === Zahlen von eine Basis in eine andere Basis umrechnen === | ||
| + | |||
| + | ibase = In welcher Basis verstehe ich deine Eingaben? | ||
| + | obase = In welcher Basis soll ich die Ergebnisse ausgeben? | ||
| + | |||
| + | > echo " | ||
| + | 11111111 | ||
| + | |||
| + | > echo " | ||
| + | 11111111 | ||
| + | |||
| + | > vim calc.bc | ||
| + | ibase=10; | ||
| + | obase=2; | ||
| + | | ||
| + | > echo " | ||
| + | 11111111 | ||
| + | |||
| + | <code c Zahlenbasis.bc> | ||
| + | obase = read(); | ||
| + | n = read(); | ||
| + | print n; | ||
| + | print " | ||
| + | </ | ||
| + | |||
| + | <code bash> | ||
| + | > for BASIS in 2 3 5 7 8 12 16; do echo " | ||
| + | 1111011 | ||
| + | 11120 | ||
| + | 443 | ||
| + | 234 | ||
| + | 173 | ||
| + | A3 | ||
| + | 7B | ||
| + | </ | ||
| + | |||
| + | |||
| + | === Zähler mit while und bc === | ||
| + | |||
| + | Dieser Zähler ist zwar etwas umständlich, | ||
| + | |||
| + | Man muss nur darauf achten, dass //bc// installiert ist. Das kleine Rechenprogramm gibt es aber schon lange für alle Uni*-Like Betriebssysteme. | ||
| + | |||
| + | |||
| + | == vorwärts == | ||
| + | |||
| + | # i=0; | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 | ||
| + | 6 | ||
| + | 7 | ||
| + | 8 | ||
| + | 9 | ||
| + | 10 | ||
| + | |||
| + | |||
| + | == rückwärts == | ||
| + | |||
| + | # i=10; | ||
| + | 9 | ||
| + | 8 | ||
| + | 7 | ||
| + | 6 | ||
| + | 5 | ||
| + | 4 | ||
| + | 3 | ||
| + | 2 | ||
| + | 1 | ||
| + | 0 | ||
| + | |||
| + | |||
| + | === Zähler mit awk === | ||
| + | |||
| + | Sonst kann man auch //awk// als Rechenknecht verwenden. | ||
| + | //AWK// gibt es für alle Uni*-Like Betriebssysteme und ist eigentlich immer schon mit drauf. | ||
| + | |||
| + | == vorwärts == | ||
| + | |||
| + | # echo " | ||
| + | 0 | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 | ||
| + | 6 | ||
| + | 7 | ||
| + | 8 | ||
| + | 9 | ||
| + | |||
| + | # echo " | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 | ||
| + | 6 | ||
| + | 7 | ||
| + | 8 | ||
| + | 9 | ||
| + | 10 | ||
| + | |||
| + | hier in Zweierschritten: | ||
| + | # echo " | ||
| + | 2 | ||
| + | 4 | ||
| + | 6 | ||
| + | 8 | ||
| + | 10 | ||
| + | |||
| + | und jetzt mit fester Zahlenlänge: | ||
| + | |||
| + | # echo " | ||
| + | 00000001 | ||
| + | 00000002 | ||
| + | 00000003 | ||
| + | 00000004 | ||
| + | 00000005 | ||
| + | 00000006 | ||
| + | 00000007 | ||
| + | 00000008 | ||
| + | 00000009 | ||
| + | 00000010 | ||
| + | |||
| + | |||
| + | == rückwärts == | ||
| + | |||
| + | # i=10 ; while (( " | ||
| + | 9 | ||
| + | 8 | ||
| + | 7 | ||
| + | 6 | ||
| + | 5 | ||
| + | 4 | ||
| + | 3 | ||
| + | 2 | ||
| + | 1 | ||
| + | 0 | ||
| + | |||
| + | # i=10 ; until [ " | ||
| + | 9 | ||
| + | 8 | ||
| + | 7 | ||
| + | 6 | ||
| + | 5 | ||
| + | 4 | ||
| + | 3 | ||
| + | 2 | ||
| + | 1 | ||
| + | 0 | ||
| + | |||
| + | Oder man rechnet gleich komplett nur mit dem //awk//. | ||
| + | |||
| + | # echo " | ||
| + | 10 | ||
| + | 9 | ||
| + | 8 | ||
| + | 7 | ||
| + | 6 | ||
| + | 5 | ||
| + | 4 | ||
| + | 3 | ||
| + | 2 | ||
| + | 1 | ||
| + | |||
| + | und jetzt mit fester Zahlenlänge: | ||
| + | |||
| + | # echo " | ||
| + | 00000010 | ||
| + | 00000009 | ||
| + | 00000008 | ||
| + | 00000007 | ||
| + | 00000006 | ||
| + | 00000005 | ||
| + | 00000004 | ||
| + | 00000003 | ||
| + | 00000002 | ||
| + | 00000001 | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | === Zähler mit seq === | ||
| + | |||
| + | * [[seq]] | ||
| + | |||
| + | Dieser Befehl ist sehr bequem aber leider gibt es ihn nicht auf jedem System und ausserdem | ||
| + | ist er in Scripten manchmal recht zickig. | ||
| + | |||
| + | == vorwärts == | ||
| + | |||
| + | # seq 1 10 | ||
| + | 1 | ||
| + | 2 | ||
| + | 3 | ||
| + | 4 | ||
| + | 5 | ||
| + | 6 | ||
| + | 7 | ||
| + | 8 | ||
| + | 9 | ||
| + | 10 | ||
| + | |||
| + | == rückwärts == | ||
| + | |||
| + | # seq 1 10 | tac | ||
| + | 10 | ||
| + | 9 | ||
| + | 8 | ||
| + | 7 | ||
| + | 6 | ||
| + | 5 | ||
| + | 4 | ||
| + | 3 | ||
| + | 2 | ||
| + | 1 | ||
| + | |||
| + | |||
| + | == Ausgabe mit fester Breite == | ||
| + | |||
| + | # seq 1 10 | sed ' | ||
| + | 000001 | ||
| + | 000002 | ||
| + | 000003 | ||
| + | 000004 | ||
| + | 000005 | ||
| + | 000006 | ||
| + | 000007 | ||
| + | 000008 | ||
| + | 000009 | ||
| + | 000010 | ||
| + | |||
| + | |||
| + | === ewig warten bis ein Ereignis eintrifft === | ||
| + | |||
| + | In diesem Fall wartet die Schleife darauf, dass ein Rechner wieder über das Netz erreichbar ist. | ||
| + | |||
| + | #!/bin/sh | ||
| + | | ||
| + | START=" | ||
| + | while [ " | ||
| + | do | ||
| + | START=" | ||
| + | sleep 1 | ||
| + | ping -c1 192.168.0.100 | ||
| + | done | ||
| + | |||
| + | DATEI=" | ||
| + | while [ -r " | ||
| + | do | ||
| + | sleep 1 | ||
| + | done | ||
| + | |||
| + | |||
| + | === nur begrenzte Zeit warten bis ein Ereignis eintrifft === | ||
| + | |||
| + | nur " | ||
| + | <file bash> | ||
| + | #!/bin/sh | ||
| + | |||
| + | DATEI=" | ||
| + | ZAEHLER=" | ||
| + | while [ ! -r " | ||
| + | do | ||
| + | ZAEHLER=" | ||
| + | sleep 1 | ||
| + | done | ||
| + | </ | ||
| + | |||
| + | oder so: | ||
| + | <file bash> | ||
| + | #!/bin/sh | ||
| + | |||
| + | DATEI=" | ||
| + | ZAEHLER=" | ||
| + | while [ " | ||
| + | do | ||
| + | ZAEHLER=" | ||
| + | if [ -r " | ||
| + | ZAEHLER=" | ||
| + | fi | ||
| + | sleep 1 | ||
| + | done | ||
| + | </ | ||
| + | |||
| + | maximal 180 Sekunden lang wartet, bis die Datenbank erreichbar ist: | ||
| + | <file bash> | ||
| + | # | ||
| + | |||
| + | MYSQL_LOGIN=" | ||
| + | ZAEHLER=" | ||
| + | |||
| + | while [ " | ||
| + | do | ||
| + | ZAEHLER=" | ||
| + | if [ " | ||
| + | ZAEHLER=" | ||
| + | fi | ||
| + | sleep 1 | ||
| + | done | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Parameter mit BASH ===== | ||
| + | |||
| + | # | ||
| + | | ||
| + | case " | ||
| + | [Ee][Ii][Nn]) | ||
| + | SCHALTEN=" | ||
| + | shift | ||
| + | ;; | ||
| + | [Aa][Uu][Ss]) | ||
| + | SCHALTEN=" | ||
| + | shift | ||
| + | ;; | ||
| + | *) | ||
| + | echo "${0} ein" | ||
| + | echo "${0} aus" | ||
| + | shift | ||
| + | exit 1 | ||
| + | ;; | ||
| + | esac | ||
| + | |||
| + | # | ||
| + | | ||
| + | while [ " | ||
| + | case " | ||
| + | -a) | ||
| + | OPTION_A=${2} | ||
| + | shift | ||
| + | ;; | ||
| + | -b) | ||
| + | OPTION_B=${2} | ||
| + | shift | ||
| + | ;; | ||
| + | -h) | ||
| + | echo " | ||
| + | HILFE: | ||
| + | ${0} [Option] | ||
| + | -a [wert a] | ||
| + | -b [wert b] | ||
| + | " | ||
| + | exit 1 | ||
| + | ;; | ||
| + | *) | ||
| + | if [ " | ||
| + | echo "Der Parameter ' | ||
| + | fi | ||
| + | shift | ||
| + | ;; | ||
| + | esac | ||
| + | done | ||
| + | | ||
| + | echo " | ||
| + | OPTION_A=${OPTION_A} | ||
| + | OPTION_B=${OPTION_B} | ||
| + | " | ||
| + | |||
| + | Soll eine Fehlermeldung ('' | ||
| + | |||
| + | statt so | ||
| + | # | ||
| + | |||
| + | kann es zum Beispiel so aussehen: | ||
| + | #!/bin/bash -eu | ||
| + | |||
| + | |||
| + | ==== Ein Beispiel mit getopts ==== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | <file bash / | ||
| + | #!/bin/sh | ||
| + | |||
| + | # wenn dieses Skript ohne Parameter aufgerufen wird | ||
| + | # dann wird eine Hilfe ausgegeben | ||
| + | if [ " | ||
| + | echo "${0} -l -u [User] -h [Host]" | ||
| + | exit 1 | ||
| + | fi | ||
| + | |||
| + | # der ":" | ||
| + | while getopts "u: h: l" OPTION | ||
| + | do | ||
| + | case ${OPTION} in | ||
| + | u) | ||
| + | USER_NAME=" | ||
| + | ;; | ||
| + | h) | ||
| + | HOST_NAME=" | ||
| + | ;; | ||
| + | l) | ||
| + | STATUS=" | ||
| + | ;; | ||
| + | esac | ||
| + | done | ||
| + | |||
| + | ### Der Parameter, der als Naechstes bearbeitet werden soll, wird bei einer Shell in der automatischen Variable OPTIND verwaltet. | ||
| + | ### Der Wert dieser Variablen betraegt beim Aufruf erst einmal 1 – wird aber bei jedem weiteren getopts-Aufruf um 1 erhoeht. | ||
| + | ### Wenn eine Kommandozeile mehrfach eingelesen werden soll, muss der Index manuell zurueckgesetzt werden. | ||
| + | #OPTIND=1 | ||
| + | |||
| + | echo " | ||
| + | OPTIND=' | ||
| + | USER_NAME=' | ||
| + | HOST_NAME=' | ||
| + | STATUS=' | ||
| + | " | ||
| + | </ | ||
| + | |||
| + | > / | ||
| + | | ||
| + | OPTIND=' | ||
| + | USER_NAME=' | ||
| + | HOST_NAME=' | ||
| + | STATUS=' | ||
| + | |||
| + | |||
| + | ===== while ohne sub-shell ===== | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | Auf die Variablen, die in einer gewöhnlichen '' | ||
| + | hat man ausserhalb der Schleife keinen Zugriff, da die '' | ||
| + | gewöhnlich mit einer Pipe gefüttert wird. | ||
| + | Wegen der Pipe wird aber eine eigene Shell geöffnet und mit ihrem Ende enden auch | ||
| + | die Variablen in ihr. | ||
| + | |||
| + | Deshalb ist die Ausgabe dieses Skripts auch leer: | ||
| + | <code bash> | ||
| + | # | ||
| + | |||
| + | VAR="" | ||
| + | echo " | ||
| + | do | ||
| + | VAR=" | ||
| + | done | ||
| + | |||
| + | echo " | ||
| + | </ | ||
| + | |||
| + | Dieses Skript liefert dagegen eine Ausgabe: | ||
| + | <code bash> | ||
| + | # | ||
| + | |||
| + | VAR="" | ||
| + | while read ZEILE | ||
| + | do | ||
| + | VAR=" | ||
| + | done < <(echo " | ||
| + | |||
| + | echo " | ||
| + | </ | ||
| + | |||
| + | Keine Pipe, | ||
| + | keine Subshell, | ||
| + | keine gestobenen Variablen. ;-) | ||
| + | |||
| + | Allserdings funktioniert das auch nicht in vollem Umfang: | ||
| + | <code bash> | ||
| + | # | ||
| + | |||
| + | VAR1="" | ||
| + | VAR2="" | ||
| + | VAR3="" | ||
| + | while read SPALTE1 SPALTE2 SPALTE3 | ||
| + | do | ||
| + | VAR1=" | ||
| + | VAR2=" | ||
| + | VAR3=" | ||
| + | done < <(echo " | ||
| + | |||
| + | echo " | ||
| + | VAR1=' | ||
| + | VAR2=' | ||
| + | VAR3=' | ||
| + | " | ||
| + | </ | ||
| + | |||
| + | Wenn die Zeile gleichzeitig noch in Spalten aufgetrennt werden soll, | ||
| + | was ja eigentlich geht, | ||
| + | dann versagt diese Methode... :-( | ||
| + | |||
| + | |||
| + | ==== Probleme mit der while-Schleife ==== | ||
| + | |||
| + | führt man in einer WHILE-Schleife komplexe Kommandos aus, dann wird oft nur das erste Kommando ausgeführt oder jedes 2. Kommando nicht ausgeführt: | ||
| + | <code bash> | ||
| + | # | ||
| + | |||
| + | # bei jeder 2. Zeile (Kommando) fehlen an Zeilenanfang, | ||
| + | |||
| + | find . -type f -iname "Air Strike_*.mkv" | ||
| + | do | ||
| + | ffmpeg -i " | ||
| + | done | ||
| + | </ | ||
| + | |||
| + | Als Lösung kann man entweder den Umweg über eine Zwischendatei gehen, die dann als statisches Skript ausgeführt wird: | ||
| + | <code bash> | ||
| + | # | ||
| + | |||
| + | # funktioniert, | ||
| + | |||
| + | find . -type f -iname "Air Strike_*.mkv" | ||
| + | do | ||
| + | Iecho " | ||
| + | done > / | ||
| + | bash / | ||
| + | rm -f / | ||
| + | </ | ||
| + | |||
| + | Oder man wählt die FOR-Schleife, | ||
| + | <code bash> | ||
| + | # | ||
| + | |||
| + | # funktioniert, | ||
| + | |||
| + | IFS=$' | ||
| + | DATEIEN=($(find . -type f -iname "Air Strike_*.mkv" | ||
| + | for FILE in " | ||
| + | do | ||
| + | ffmpeg -i " | ||
| + | done | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== leere Unterverzeichnisse löschen ===== | ||
| + | |||
| + | '' | ||
| + | > rmdir Verzeichnis/ | ||
| + | |||
| + | ohne Fehlermeldung kann man das so machen: | ||
| + | > DIR=" | ||
| + | |||
| + | leeren Unterverzeichnisse kann man mit ''// | ||
| + | |||
| + | |||
| + | ===== Alphabet generieren ===== | ||
| + | |||
| + | > echo {a..z} | ||
| + | a b c d e f g h i j k l m n o p q r s t u v w x y z | ||
| + | |||
| + | |||
| + | ===== cooler Prompt ===== | ||
| + | |||
| + | Wenn man als privilegierter Benutzer angemeldet ist, ist der Benutzername im Prompt pink, | ||
| + | ist man als unprivilegierter Benutzer angemeldet ist, ist der Benutzername im Prompt hellblau. | ||
| + | Der Hostname ist immer dunkelblau. | ||
| + | |||
| + | Andere Farben kann man nach belieben konfigurieren, | ||
| + | |||
| + | Die erste Zahl vor der Uhrzeit zeigt den Exit-Code an: | ||
| + | |||
| + | [root@rechner]---------------------------------------------------[0]-[0]-[14: | ||
| + | [~]# false | ||
| + | | ||
| + | [root@rechner]---------------------------------------------------[1]-[0]-[14: | ||
| + | [~]# | ||
| + | |||
| + | Die zweite Zahl gibt die Anzahl der im Hintergrund laufenden Job's an. | ||
| + | |||
| + | [root@rechner]---------------------------------------------------[0]-[0]-[14: | ||
| + | [~]# sleep 60 | ||
| + | ^Z | ||
| + | [1]+ Angehalten | ||
| + | | ||
| + | [root@rechner]-------------------------------------------------[148]-[1]-[14: | ||
| + | [~]# bg 1 | ||
| + | [1]+ sleep 60 & | ||
| + | | ||
| + | [root@rechner]---------------------------------------------------[0]-[1]-[14: | ||
| + | [~]# | ||
| + | | ||
| + | [root@rechner]---------------------------------------------------[0]-[1]-[14: | ||
| + | [~]# | ||
| + | [1]+ Fertig | ||
| + | | ||
| + | [root@rechner]---------------------------------------------------[0]-[1]-[14: | ||
| + | [~]# | ||
| + | | ||
| + | [root@rechner]---------------------------------------------------[0]-[0]-[14: | ||
| + | [~]# | ||
| + | |||
| + | |||
| + | === mach_bash_prompt.sh === | ||
| + | |||
| + | Dieses Skript nimmt den entsprechenden Eintrag in der datei '' | ||
| + | und erstellt die Datei'' | ||
| + | |||
| + | # | ||
| + | | ||
| + | echo " | ||
| + | [ -f ~/ | ||
| + | export EDITOR=vi | ||
| + | " >> ~/.bashrc | ||
| + | | ||
| + | (echo ' | ||
| + | PROMPT_COLORS=${PROMPT_COLORS: | ||
| + | | ||
| + | prompt_command() { | ||
| + | local EC=" | ||
| + | | ||
| + | case " | ||
| + | *) | ||
| + | local CUSER=" | ||
| + | local CHOST=" | ||
| + | local CEC=" | ||
| + | local CJOBS=" | ||
| + | local CTIME=" | ||
| + | local CDIR=" | ||
| + | local CAT=" | ||
| + | local CWARN=" | ||
| + | local CDEF=" | ||
| + | ;; | ||
| + | esac | ||
| + | | ||
| + | local R=" | ||
| + | | ||
| + | local USER=$(whoami) | ||
| + | local HOSTNAME=$(hostname) | ||
| + | local JOBS=$(jobs|wc -l) | ||
| + | local PWD=$(pwd) | ||
| + | local TIME=" | ||
| + | | ||
| + | PWD=${PWD/# | ||
| + | [ " | ||
| + | | ||
| + | local TMP=" | ||
| + | [ -n " | ||
| + | | ||
| + | local SP=" | ||
| + | [ ${#TMP} -gt 0 ] && local SPACER=$(printf " | ||
| + | SPACER=${SPACER// | ||
| + | | ||
| + | [ $EC -gt 0 ] && EC=" | ||
| + | [ $JOBS -gt 0 ] && JOBS=" | ||
| + | [ $UID -eq 0 ] && USER=" | ||
| + | [ -n " | ||
| + | | ||
| + | PS1=" | ||
| + | $R[$USER\[\e[${CAT}m\]@$HOSTNAME$R]$SPACER\ | ||
| + | [$EC$R]$SP[$JOBS$R]$SP[\[\e[${CTIME}m\]$TIME$R] | ||
| + | [\[\e[${CDIR}m\]$PWD$R]\\\$\[\e[0m\] " | ||
| + | } | ||
| + | | ||
| + | PROMPT_COMMAND=prompt_command | ||
| + | | ||
| + | [ " | ||
| + | set_screen_title() { | ||
| + | while [ 1 ] ; do | ||
| + | case " | ||
| + | sudo|prompt_command|-*) shift ;; | ||
| + | *) break ;; | ||
| + | esac | ||
| + | done | ||
| + | echo -en " | ||
| + | } | ||
| + | ' | ||
| + | echo " | ||
| + | } | ||
| + | ") > ~/ | ||
| + | |||
| + | |||
| + | === ~/.bashrc === | ||
| + | |||
| + | Dieser Eintrag überprüft, | ||
| + | und bindet sie ein, wenn es sie hier gibt. | ||
| + | |||
| + | [ -f ~/ | ||
| + | export EDITOR=vi | ||
| + | |||
| + | |||
| + | === ~/ | ||
| + | |||
| + | Diese Datei enthält die speziellen Einstellungen für unseren coolen Prompt. | ||
| + | |||
| + | PROMPT_COLORS=${PROMPT_COLORS: | ||
| + | | ||
| + | prompt_command() { | ||
| + | local EC=" | ||
| + | | ||
| + | case " | ||
| + | *) | ||
| + | local CUSER=" | ||
| + | local CHOST=" | ||
| + | local CEC=" | ||
| + | local CJOBS=" | ||
| + | local CTIME=" | ||
| + | local CDIR=" | ||
| + | local CAT=" | ||
| + | local CWARN=" | ||
| + | local CDEF=" | ||
| + | ;; | ||
| + | esac | ||
| + | | ||
| + | local R=" | ||
| + | | ||
| + | local USER=$(whoami) | ||
| + | local HOSTNAME=$(hostname) | ||
| + | local JOBS=$(jobs|wc -l) | ||
| + | local PWD=$(pwd) | ||
| + | local TIME=$(date +%H:%M) | ||
| + | | ||
| + | PWD=${PWD/# | ||
| + | [ " | ||
| + | | ||
| + | local TMP=" | ||
| + | [ -n " | ||
| + | | ||
| + | local SP=" | ||
| + | [ ${#TMP} -gt 0 ] && local SPACER=$(printf " | ||
| + | SPACER=${SPACER// | ||
| + | | ||
| + | [ $EC -gt 0 ] && EC=" | ||
| + | [ $JOBS -gt 0 ] && JOBS=" | ||
| + | [ $UID -eq 0 ] && USER=" | ||
| + | [ -n " | ||
| + | | ||
| + | PS1=" | ||
| + | $R[$USER\[\e[${CAT}m\]@$HOSTNAME$R]$SPACER\ | ||
| + | [$EC$R]$SP[$JOBS$R]$SP[\[\e[${CTIME}m\]$TIME$R] | ||
| + | [\[\e[${CDIR}m\]$PWD$R]\\\$\[\e[0m\] " | ||
| + | } | ||
| + | | ||
| + | PROMPT_COMMAND=prompt_command | ||
| + | | ||
| + | [ " | ||
| + | set_screen_title() { | ||
| + | while [ 1 ] ; do | ||
| + | case " | ||
| + | sudo|prompt_command|-*) shift ;; | ||
| + | *) break ;; | ||
| + | esac | ||
| + | done | ||
| + | echo -en " | ||
| + | } | ||
| + | trap ' | ||
| + | } | ||
| + | |||
| + | |||
| + | ===== Array ===== | ||
| + | |||
| + | Array (also mit Index): ${array[0]}, | ||
| + | Map (also mit Key) : ${array[" | ||
| + | |||
| + | Array ist wie eine Liste, in der jedes Element ein Index hat und '' | ||
| + | |||
| + | |||
| + | ==== mit explizitem Index ==== | ||
| + | |||
| + | |||
| + | === ReadArray === | ||
| + | |||
| + | > readarray -t testarray < <(find Videos/ -type f) | ||
| + | > echo " | ||
| + | > echo " | ||
| + | |||
| + | > find Videos/ -type f > / | ||
| + | > readarray -t testarray < / | ||
| + | > echo " | ||
| + | > echo " | ||
| + | |||
| + | |||
| + | ==== mit implizitem Index ==== | ||
| + | |||
| + | > export ARRAY=(127 0 255) | ||
| + | > echo ${ARRAY[@]} | ||
| + | 127 0 255 | ||
| + | > echo ${# | ||
| + | 3 | ||
| + | > echo ${# | ||
| + | 127 | ||
| + | > echo ${# | ||
| + | 0 | ||
| + | > echo ${# | ||
| + | 255 | ||
| + | |||
| + | > arrayLaenge=${# | ||
| + | > echo "Das Array enthält ' | ||
| + | Das Array enthält ' | ||
| + | |||
| + | > testarray=($(find Videos/ -type f)) | ||
| + | > echo " | ||
| + | > echo " | ||
| + | |||
| + | **ACHTUNG!** | ||
| + | |||
| + | __Es funktioniert mit **'' | ||
| + | |||
