Nützliches für die Kommandozeile
Übersicht über das Konsolen-Tutorial
Zerlegung in Eingabeelemente[Bearbeiten]
Eine Shell zerlegt die Eingabe in einzelne Eingabeelemente, die dann mit den unten beschriebenen Ersetzungen bearbeitet werden.
- Ein String ist eine mit Stringtrennern eingeschlossene Zeichenfolge.
- Stringtrenner sind einfacher und doppelter Apostroph: ' und ".
- Ein Wort ist die jeweils längstmögliche Zeichenfolge ohne Trennzeichen
- Trennzeichen sind in der Variablen $IFS festgelegt, standardmäßig Leerzeichen, TAB und NEWLINE.
- Ist ein Eingabelement ein String, ist es kein Wort
echo "1 oder 2" Beispiele 'gefällig?'
Die Shell erkennt 4 Eingabeelemente:
- echo
- "1 oder 2"
- Beispiele
- 'gefällig?'
Ersetzungen[Bearbeiten]
Die Bash kennt eine ganze Reihe von Abkürzungen und Ersetzungen:
Ergänzung des Dateinamens[Bearbeiten]
Kommen in einem Wort (nicht String) die Zeichen *, [] oder ? vor, wird dieses Wort durch alle Dateinamen ersetzt, die auf das dadurch gegebene Muster passen. Muster deshalb, weil die oben genannten Platzhalter auf mehrere Dateinamen passen können.
Die Bedeutung der Platzhalter:
- *: Es können beliebig viele Zeichen an dieser Stelle sein, also auch gar kein Zeichen.
- ?: Es ist genau ein Zeichen vorhanden.
- [<liste>]: Es kommt genau ein Zeichen aus der Liste vor. Die Liste besteht aus einer Aufzählung von Einzelzeichen und von Bereichen, wobei letztere durch Anfang, '-' und Ende gebildet werden.
- [aeiou]: Es kommt genau ein Vokal vor
- [0-9a-fA-F]: Es kommt genau eine Hexziffer vor
- [^<liste>]: Es kommt kein Zeichen aus der Liste vor.
- [^0-9]: Ein Zeichen, das keine Ziffer ist
- [^-._]: Ein Zeichen, aber nicht '-', '.' oder '_'
Beispiele[Bearbeiten]
Voraussetzung für Nachmachen schaffen:
mkdir -p /tmp/bashtest/dir ; cd /tmp/bashtest ; touch a1.txt a2.txt alles.txt nix.txt a10.txt dir/b1.txt dir/b2.txt
Fängt mit a an, hört mit .txt auf:
echo a*.txt
a10.txt a1.txt a2.txt alles.txt
Fängt mit zwei Zeichen an, hört mit .txt auf:
echo ??.txt
a1.txt a2.txt
Da Verzeichnisse unter Unixoiden genauso Dateien sind, funktioniert auch:
Verzeichnis fängt mit d an, im Dateinamen kommt eine '1' oder '2' vor:
echo d*/*[12]*
dir/b1.txt dir/b2.txt
Aufgabe: Gib einen Ausdruck an, mit dem diese Ausgabe erzeugt wird:
alles.txt nix.txt
Negation[Bearbeiten]
Manchmal ist es nützlich, Ausnahmen angeben zu können. Das geht mit !(<muster>):
echo !(??.*)
Alles, was nicht 2 Zeichen vor .txt hat:
a10.txt alles.txt dir nix.txt
Jedes Wort einzeln[Bearbeiten]
Die Shell expandiert jedes Wort einzeln. Es werden also keine Dupletten ausgesiebt.
echo !(*.txt) a* ??.txt
dir a10.txt a1.txt a2.txt alles.txt a1.txt a2.txt
- Das erste Wort erzeugt dir
- Das zweite Wort erzeugt a10.txt a1.txt a2.txt alles.txt
- Das 3.te Wort erzeugt a1.txt a2.txt
Generelle Ausnahmen[Bearbeiten]
Mit der Variablen $GLOBIGNORE kann Muster angeben, getrennt mit ':'. Jede Datei, die auf eines dieser Muster passt, erscheint nicht in der Expansion.
GLOBIGNORE=*1.*:?i*
echo *
a10.txt a2.txt alles.txt
Die geschweiften Klammern[Bearbeiten]
Mit geschweiften Klammern können Wörter durch Kombination erzeugt werden. Dies ist eine rein textuelle Operation und hat nichts mit Dateinamen zu tun!
Die erste Form nutzt Aufzählungen:
echo Fall{1,2,5}
Fall1 Fall2 Fall5
Die zweite Form operiert auf Intervallen, evt. mit Schrittweite:
echo Fall_{1..4}
echo Plan_{10..16..2}
# auch mehrfach (dann alle Kombinatinen):
echo X{a..f}{0..2}
Fall_1 Fall_2 Fall_3 Fall_4 Plan_10 Plan_12 Plan_14 Plan_16 Xa0 Xa1 Xa2 Xb0 Xb1 Xb2 Xc0 Xc1 Xc2 Xd0 Xd1 Xd2 Xe0 Xe1 Xe2 Xf0 Xf1 Xf2
Tilde[Bearbeiten]
- Steht das Zeichen ~ am Anfang eines Wortes (nicht Strings), wird diese durch die Variable $HOME (das Heimatverzeichnis des angemeldeten Benutzers) ersetzt.
- Steht am Anfang ein ~+, findet eine Ersetzung mit $PWD (aktuelles Verzeichnis) statt.
- Beginnt das Wort mit ~-, wird $OLDPW eingesetzt (Vorgänger des aktuellen Verzeichnisses)
cd /tmp ; cd /tmp/bashtest
echo ~ XXX ~+/dir YYY ~-/bash*
/home/hm XXX /tmp/bashtest/dir YYY /tmp/bashtest
Die Tilde-Ersetzung wird zuerst durchgeführt, dann erfolgt noch eine Ergänzung der Dateienamen.
Anwendungsbeispiele[Bearbeiten]
Alle Textdateien des aktuellen Verzeichnisses in den Ordner merken im Heimatverzeichnis legen:
mkdir ~/merken ; ln -s ~+/*.txt ~/merken
Hinweis: Das Kommando ln benötigt in diesem Fall absolute Pfade.
Ein vorausgegangenes cd (change directory) rückgängig machen:
cd ~-
Expansion verhindern (Quoting)[Bearbeiten]
Was machen wir, wenn wir keine Dateinamen- oder Geschweiftklammer-Expansion wollen? Dazu gibt es 2 Methoden:
- Vor die Sonderzeichen einen Backslash \ setzen: echo geht es noch\?
- Aus dem Wort einen String machen:
- echo "Geht es noch?"
- echo 'Geht es noch?'
Anwendungsbeispiel[Bearbeiten]
Das prominenteste Beispiel ist wohl die Verwendung von -exec im Kommando find. Mit dieser Option kann man mit allen gefundenen Dateien "was machen". An der Stelle, an der die Datei in der Ausgabe erscheinen soll, ist der Platzhalter {} einzusetzen, das Ende der Ausgabe ist mit ; zu markieren.
Wir wollen die Anzahl der Wörter in allen Textdateien im Unterverzeichnis dir zählen:
find dir -name *.txt -exec wc -w {};
find: Der Pfad muß vor dem Suchkriterium stehen: a2.txt
Was ist passiert? Schauen wir der Shell zu, was sie macht:
set -x
find dir -name *.txt -exec wc -w {} ;
+ find dir -name a10.txt a2.txt alles.txt -exec wc -w '{}' find: Der Pfad muß vor dem Suchkriterium stehen: a2.txt
Die Bash hat den Ausdruck *.txt expandiert (in a10.txt a2.txt alles.txt), damit stimmt die Syntax von find nicht mehr. Also müssen wir die Expansion verhindern durch Stringbildung "*.txt".
Aber wo ist der Strichpunkt am Ende geblieben? Die Bash hat den Strichpunkt als Trenner zum nächsten Kommando aufgefasst und entfernt. Daher müssen wir quoten, z.B. mit \;
find dir -name "*.txt" -exec wc -w {} \;
set +x
+ find dir -name '*.txt' -exec wc -w '{}' ';' 0 dir/b1.txt 0 dir/b2.txt
Jetzt leistet find das Gewünschte.
Hinweis: Oft findet man in Beispielen von find, dass auch {} gequotet wird. In der Bash ist das, wie oben gesehen, nicht notwendig: Die geschweiften Klammern werden nur ersetzt, wenn sich darin eine Liste befindet.
Strings und Variablenersetzung[Bearbeiten]
Der Unterschied von und "": Variablen werden innerhalb "" ersetzt, in nicht:
echo "Ich bin in $HOME zu Hause"
Ich bin in /home/hm zu Hause
echo '$HOME ist das Heimatverzeichnis'
$HOME ist das Heimatverzeichnis