====== Codeschnipsel für Shell-Programmierung ====== Eine kleine Auswahl an Codeschnipseln für bestimmte Aufgaben in Shell-Skripten. ==== Sichere Verwendung von Variablen ==== ${VAR:?} Überprüft, ob die Variable gesetzt ist statt eines leeren Strings zu verwenden. Negativbeispiel: [[linux:steam|Steam unter Linux]], Valve hatte rm -rf "$STEAMROOT/"* im Code stehen, $STEAMROOT kann leer sein. Dadurch wird der Befehl zu ''rm -rf /*''. Kann durch ''${STEAMROOT:?}'' verhindert werden, da so mit einem Fehler abgebrochen wird, wenn die Variable leer oder nicht gesetzt ist. ==== Dateiendungen entfernen ==== name=${$path%.*} ''%'' löscht den kürzesten Treffer vom Ende des Strings, ''%%'' löscht den längsten Treffer vom Ende aus. ==== Kompletten Pfad entfernen ==== name=${$path##*/} ''#'' löscht den kürzesten Treffen vom Beginn des Strings, ''##'' löscht den längsten Treffer vom Beginn aus. ==== Letzten Teil des aktuellen Pfades entfernen (basename) ==== "${PWD%/*}" ==== Zum Vorherigen Verzeichnis wechseln ==== cd - ==== Basispfad des ausgeführten Skripts ermitteln ==== DIR=$( cd -- "$( dirname -- "$(readlink -f "${BASH_SOURCE[0]}" || ${BASH_SOURCE[0]})" )" &> /dev/null && pwd ) Folgt auch Symlinks und funktioniert, wenn es mit ''source'' ausgeführt wird, ''#!/bin/sh'' hat bei mir ebenfalls geklappt. ==== Formatierung ''date'' ==== date +"%A, %e. %B %Y %k:%M:%S %Z" Liefert eine Ausgabe in der Form "Donnerstag, 1. Januar 1970 0:00:00 CET" ==== printf rechts ausrichten ==== col=$(tput cols) printf '%*s%s' $col "[OK]" Oder als Einzeiler printf '%*s%s' $(tput cols) "[OK]" ==== watch mehrere Argumente mehrzeilig ==== watch -t -n 10 'printf "%*s%s" $(tput cols) "$(date)"; echo -e "\n" \ && echo "Jobs running:" && qstat | grep R | grep $USER | wc -l' ==== Installationszeitpunkt Linux ermitteln ==== sudo tune2fs -l $(mount | grep 'on \/ ' | awk '{print $1}') | grep 'Filesystem created:' | awk '{print $5, $4, $7}' ==== Array ohne Dopplungen ausgeben ==== awk '!a[$0]++' file Entfernt doppelte Einträge ohne sortieren. ''$0'' bedeutet die ganze Zeile in ''awk'', ''%%'a'%%'' steht für Array, Ausgabe falls nicht in Array. ==== Berechnungen, Zahlen runden ==== Berechnungen allgemein können mit ''bc'' ausgeführt werden: echo "3.14+7/8-(5.42*3.14)" | bc Das ganze lässt sich auch mit ''printf'' formatieren: printf "%.3f\n" $(echo 5/3 | bc -l) Allerdings bereitet dies in Sprachen Probleme, in denen ein Komma statt eines Punkts als Dezimaltrennzeichen verwendet wird. Alternative: round(){ local l=$2 [ "$l" == "" ] && l=2 # use 2 decimal places if not specified echo "scale=$l;(10^$l*$1+0.5)/10^$l" | bc -l | sed 's/^\./0./' # last sed adds leading zero in case of numbers smaller than 1 (bc returns e. g. .7 instead of 0.7) } Beispielaufrufe: round 42/3.14159 round 17/13 7 ==== Überprüfen, ob Kernel-Module geladen sind ==== #!/bin/sh # check if a kernel module is loaded [ "$1" == "" ] && echo "Usage: $0 MODULE [q]" && exit 0 #if lsmod | grep -Eq "$1" &> /dev/null ; then if grep -Eq "$1" /proc/modules &> /dev/null ; then [ "$2" == "q" ] || echo "$1 is loaded!" exit 0 else [ "$2" == "q" ] || echo "$1 is not loaded!" exit 1 fi {{tag>linux shell bash scripting programming}}