Begonnen: Fre Okt 17 13:00:00 CET 1997 Zuletzt editiert: Fre Mai 6 13:02:43 CEST 2005 Willkommen zur ersten deutschen Zsh-Seite!Die Zsh (sprich Z-Shell) ist eine herausragende, aber im Verhältnis zur Bash ziemlich unbekannte Shell, also ein befehlsorientierter Eingabemechanismus, über den man vor allem Befehle unter Unix interaktiv eingeben kann und außerdem Befehle automatisieren und Abläufe programmieren kann. Sie ist im Falle der Zsh mit einer mächtigen Programmiersprache durchaus gleichzusetzten, wenn dabei auch kein Maschinencode erzeugt wird.
Warum ich diese Seite gemacht habe?
Ich halte die Zsh für herausragend in Benutzerfreundlichkeit und Mächtigkeit. Sie macht mir das Arbeiten auf der Kommandozeile zur Freude, besticht durch ungeheure Anpassungsfähigkeit und hilft mir, wenn ich mich einmal wieder nicht genau an irgendwelche Optionen bei Befehlen erinnere. Zusätzlich kann sie vieles, was andere Shells nur durch externe Befehle möglich machen. Ich selber stieß beim Lesen der Linux-Gazette zum ersten Mal auf die Zsh. Ein Benutzer hatte dort in einer Email zum Thema "Umwandlung von großen Buchstaben von Dos-Dateien nach Linux" eine sehr einfache und kurze Lösung durch die Zsh berichtet .(siehe unten).
Genau dafür ist die Zsh wie geschaffen. Ich kann damit Probleme mit wenigen Tastenanschlägen lösen.Auf einer Homepage über unterschiedliche Shells las ich, die Zsh könne wahrscheinlich mehr als der Autor selber wisse. Natürlich hat das seinen Preis in der Größe der Shell und in der Größe des Handbuchs. Puristen werden die Zsh wohl nicht unbedingt benutzen. Aber wer sagt denn, dass man nicht in einer Sache Purist und in einer anderen sehr großzügig oder gar verschwenderisch sein kann oder dass man nicht für bestimmte Aufgaben so und für andere anders verfährt, je nach Bedarf, Speicherplatz, Rechnergeschwindigkeit?
Hier findet sich die Beschreibung der Z-Shell vom ihrem ursprünglichen Autor Paul Falstad, der übrigens durch einen Zhong Shao (heute Professor in Yale, seinerzeit Assistent in Princeton) mit Benutzername zsh auf diesen Namen kam. :) Der ursprüngliche Autor beschrieb 1991 die Vorzüge dieser 1990 begonnenen Shell. Trotz seines Alters kann dieser längere Artikel Neugier wecken. Zumindest bei Sven Wischnowsky, einem der wichtigsten Zsh-Entwickler seit 1992 (ihm verdankt die Zsh ihre Vervollständigungsmechanismen und vieles mehr) und 1997 bei mir war der Artikel der Anlass, auf die Z-Shell umzusteigen. Und die Shell hat heutzutage noch so viele praktische Fähigkeiten dazu bekommen!
Seit neuerer Zeit (1999) gibt es diesen neuen Zsh-Guide von Peter Stephenson, einem anderen wichtigen Entwickler der Z-Shell, der mit großer Liebe zum Detail, mit Witz und ,wie ich finde, sehr verständlich auf die Zsh und ihre Möglichkeiten eingeht und von dem bald sogar ein gedrucktes Buch über diese Shell erscheinen soll!
Leider ist diese tolle Shell, die es gerade Anfängern so viel leichter machen könnte und Power-Usern eine Unzahl an Möglichkeiten bietet, z.B. unter Linux-Kreisen relativ unbekannt, obschon sie erhebliche Vorteile gegenüber der Bash hat und gegenüber der Tcsh auch eine ziemlich große Ähnlichkeit mit der Ksh und der Bourne-Shell aufweist und sich auch fuer Skripte ausgesprochen eignet.
Fähigkeiten, die mich an der Zsh faszinieren:
- Ich brauche kaum umzulernen: Die meisten Kommandos sind so, wie ich es von der Bash und der Ksh, die sie vor allem nachahmt, kenne.
Oft kann ich auch durch eine Beschreibung der Ksh eine Menge lernen. Diese ist nämlich in vielen älteren Unix-Büchern ausführlich beschrieben.
- Für Umsteiger bietet die Zsh einen Emulationsmodus für Sh,Csh und Ksh an.
Beispielsweise versuchtemulate sh, die SH zu emulieren. (siehe auchman zshbuiltinsunter emulate.)
Außerdem zwingt die Shell dem Anwender nie ein bestimmtes Verhalten auf. Mit über 150 Optionen läßt sich ihr Verhalten sehr flexibel an den Geschmack und die Bedürfnisse des Benutzers anpassen.
So kann man mit der Z-Shell falsche Eingaben korrigieren lassen, ist aber dazu in keiner Weise gezwungen: (unsetopt correct) und die Vervollständigungen sind bis ins allerkleinste Detail anpassbar.
- Die Zsh ist ausgesprochen modular (über 20 Module). Damit ist der Nutzer in der Lage, ganz nach Bedarf bestimmte Features zu benutzen und andere völlig auszusparen.
So hat die Zsh z.B. ein Mathematik-Modul mit über 30 mathematischen Funktionen, die viele Anwender nicht brauchen werden, für manche aber sehr nützlich sind. Gleiches gilt für das Profiler-Modul (zprof), ein mit den internen Vervollständigungen arbeitendes Ftp-Modul (zftp), das Pseudoterminal-Modul zur Automatisierung von Programmen, die ein Terminal erwarten (zpty), u.s.w...
- Die Zsh kann Funktionen mit
zcompilein eine für den Computer schneller zu lesende binäre Ausführungsform bringen. Dabei wird ein Word-Code ähnlich dem Java-Bytecode erzeugt, nur, dass dabei words (2 Bytes) benutzt werde. So kann man die Funktionen erheblich beschleunigen.
- Intuitiv (wie in Perl, Python, Ruby) lassen sich in Zeichenketten Ersetzungen durch Zeichenketten-Indices machen:
a="ich hab nix gemacht.";a[1]='I';a[-1]='. (Bart Simpson)'
- Die Zsh unterstützt assoziative Arrays (Variablen-Felder mit Buchstaben als Index):
typeset -A ass_array; ass_array=( eins 1 zwei 2 drei 3 vier 4)deklariert und definiert eine auch Hash genannte Feldvariable, deren einzelne Elemente einen Index aus Buchstaben besitzen.print $ass_array[eins]gibt im Beispiel das erste Element, 1, aus,print ${(k)ass_array}gibt die Keys (Schlüssel),print ${(v)ass_array}die Values (Werte).
- Temporäre unbenannte Variablen ermöglichen es, Teile aus Zeichenketten zu extrahieren und alle möglichen Umwandelungen durchzuführen:
print ${$( date )[1]}gibt das erste Wort, was date liefert, aus. Dazu muss der Befehldatein$()angegeben werden (die alte Bourne-Shell Schreibweise innerhalb von``funktioniert hier nicht!).
$(date)wird umschlossen von${[1]}, was das erste Wort hervorbringt. Diese Konstruktion kann man beliebig verschachteln, was nur den Nachteil besitzt, sehr unleserlich mit größerer Verschachtelungstiefe zu werden.
print ${${$( LC_ALL=de_DE /sbin/ifconfig ppp0 )[5]}#Adresse:}könnte bei Verwendung von pppd unter Linux die Ip-Adresse ausgeben, wobei nebem dem eben gezeigten Mechanismus zusätzlich die Zeichenkette "Adresse:" gelöscht wird.
Es ist auch möglich, head, tail, uniq, sort und sogar grep durch interne Mechanismen zu ersetzen.
Dazu muss so vorgegangen werden, dass der Modifier(f)im Index der unbenannten Variablen Verwendung findet. Dies führt dann dazu, dass bestimmte Zeilen statt Buchstaben durch den Index ausgewählt werden:
print -l ${"$( < datei )"[(f)5]}gibt die Zeile 5 aus "datei" aus.
print ${"$( < /etc/passwd )"[(fr)*root*]}gibt die erste Zeile, in der "root" vorkommt, an, wobei in diesem Fall im Index nach einem Muster (hier: "*root*") gesucht wird mittels(r).
- Als regelrechtes grep mit allen Vorkommen kann man folgenden Mechanismus benutzen:
print -l ${(M)${(f)"$(< /etc/passwd)"}##*$muster*}(f)liest die in Anführungsstrichen stehende Ausgabe der Datei zeilenweise in eine unbenannte Variable. Wie auch in anderen Shells schneidet##am Anfang*$muster*ab.
Da aber(M)benutzt wird, werden alle Zeilen, bei denen das Muster zutrifft, nicht abgeschnitten, sondern allein ausgegeben. Das Gegenstück dazu ist (R), was im vorigen Fall dann einem "grep -v" entspricht.
Würde man nur ein#angeben, würden die Sterne, Stellvertreter fuer 0 oder mehr Zeichen, geizig, mit so wenig Zeichen wie möglich, ausgegeben. In diesem Fall würde dann also nur$musterselber ausgeben.
- Mit sogenannten Flags in der Variable können viele verschiedene Manipulationen an Variablen gemacht werden:
Beispielsweise kann man Arrays mit einem Delimiter "joinen" (vereinen):
a=(eins zwei drei) b=${(j:,:)a}; print $b
Man kann eine Variable auf"splitten" (aufteilen), so dass ein Array entsteht:
b="eins,zwei,drei" c=${(s:,:)b}; print $c[1]
Man kann Buchstaben oder Worte zählen:
echo "eins zwei drei vier fuenf" | while read zeile ; do print "$zeile:" ${(c)#zeile} ; done- Zsh kann wie bekanntere Programmiersprachen (Perl, Python, Ruby z.B) im Index einer Variablen ein "von_feld,bis_feld".
print ${$( date )[2,4]}gibt vom zweiten bis vierten Wort das von "date" gelieferte Ergebnis aus. Oder es geht auch mit negativen Index:print ${${:-eins zwei drei vier fuenf}[2,-2]}gibt als Ergebniszwei drei vieraus. (:-ersetzt den fehlenden Variablennamen hier wie bei der Bash durch seine Werte).
Bei Arrays ist es auch möglich, zweidimensionale Indices zu gebrauchen:
print ${$(date)[4][1,5]}gibt die Uhrzeit von date ohne Sekunden aus.
- Mit Hilfe des Moduls
pcrekann die Zsh seit Version 4.1.1 Perls reguläre Ausdrücke verarbeiten. Dazu lädt man mitzmodload zsh/pcredas PCRE-Modul ein, kompiliert dann einen beliebigen perlartigen regulären Ausdruck mit Hilfe vonpcre_compileund verarbeitet anhand des Fehlercodes 1 bzw. 0 alles weitere. Beispiel:pcre_compile '\s\d\.\d{3}\.\d{3} Euro' &&\ pcre_match ' 1.000.000 Euro'\ && echo "Trifft zu!" || echo "Trifft nicht zu!"Bei komplexeren Ausdrücken kann man die Geschwindigkeit noch durch pcre_study verbessern.
- Mit dem sogenannten Here-String kann man eine Art Here-Document benutzen ohne ein EOT-Signal auf einer Extra-Zeile eingeben zu müssen.
for Programm in cat tail head grep ; do >> /tmp/datei <<< "Hallo,Welt! Ich habe das Geüfhl, mein externes $Programm wird bald nicht mehr so viel benutzt." ; done
Man achte auch auf das Auslassen von cat, was bei der zsh nicht mehr nötig ist!
- Flieskommazahlen können berechnet werden:
printf "%.0f\n" $[ 2.8*15 ].
Ausserdem kann in verschiedenen Zahlensystemen gerechnet werden, indem in eckigen Klammern[#<zahlensystem>]geschrieben wird, also:for (( i=1; i<100; i++ )) { print $(( [#10] i)) entspricht $(( [#16] i )) }Bei zweifacher Angabe von#wird das Zahlensystem nicht ausgegeben.
Sogar einen "Taschenrechner" gibt es in der Zsh, der nachautoload zcalczur Verfügung steht.
- Die Zsh kann alles vervollständigen, was man sich so ungefähr vorstellen kann. (siehe auch
zshcompctlund seit 3.1.6zshcompsys. (Programmierbare Vervollständigung ist für die Bash erst seit April 2000 (Version 2.04) und bei der Ksh gar nicht vorhanden. Seit Zsh 4.1 können sogar die Vervollständigungsmechanismen der Bash genutzt werden unter Verwendung von bashcompinit.)
Mit der Version 3.1.6 wird eine neue Richtung in der Programmierung von Vervollständigungen vorgelegt.
Statt mit Optionen läßt sich der Ergäzungsmechanismus der Shell nun sehr viel einfacher durch den Aufruf von über 400 vordefinierten Funktionen programmieren.
Das hat den Vorteil:
Für sehr viele Bereiche läßt sich durch Kopieren und Editieren schnell eine neue Vervollständigung fertigstellen, da man jetzt nicht mehr so detailiert wissen muß, wie die neuen Vervollständigungen zu programmieren sind. Außerdem muß man häufig sogar einfach nur mitautoload compinit && compinitden neuen Mechanismus blind in Gang setzen und kann direkt vorgefertigte Vervollständigungs-Mechanismen nutzen. Man rufe danach beispielsweise einmalxterm -fnauf. (siehe auch hier)
Beispiele zur Vervollständigung (noch nach dem alten Schema bis 3.1.5):
compctl -g '*(/)' cdmacht aus einer einfachen Dateiergänzung wie der Ksh eine intelligente Vervollständigung für "cd", die nur noch Verzeichnisnamen aufführt.
Vor allem mitcompctl -k '(`aktion`)'lassen sich sehr praktische Vervollständigungsmechanismen erstellen. Man kann sich so z.B ohne Probleme bei Aufruf eines Email-Programmes nur Email-Adressen und mit ftp nur FTP-Adressen vervollständigen lassen. Außerdem kann man bei der Vervollständigung auch Dateienden abschneiden lassen. Das ist z.B bei Java sehr praktisch.(Mehr Beispiele zur älteren Vervollständigung hier)
compctl -g '*.class(:r)' java
- Mit der Zsh kann man sehr gezielt nach Worten in Dateien suchen: Nach dem Freischalten von Sonderzeichen für die Reichweite eines glob-Befehls mit
setopt extended_globist folgendes machbar:
grep Wort *~(*.gz|*.bz|*.bz2|*.zip|*.Z)sucht Wort nicht mehr in meinen komprimierten Dateien in meinem Mail-Ordner.
~bedeutet hier so viel wie "außer".
Alle Dateien, die nicht die Endung *.bz2 und auch nicht *.gz enthalten , sucht man mitls ^(*.bz2|*.gz). Das^ist also das "NICHT", das Ausrufezeichen wird von der Zsh für alte Befehle benutzt, deshalb.
An dieser Stelle bietet sich vielleicht ein globales Alias für komprimierte Dateien an (siehe weiter unten).
Zusätzlich zu^und~lassen sich die Ausdrücke#und##benutzen, um null und mehr bzw. ein und mehr Vorkommen des Zeichens davor zu erhalten, was bei Perls regulären Ausdrücken den Zeichen*bzw.+entspricht.
- Globale Aliase sind Aliase, die nicht nur am Anfang der Kommandozeile oder nach
;als Aliase wirken können. Sie sollten gut gekennzeichnet werden:
alias -g §k="*~(*.bz2|*.gz|*.tgz|*.zip|*.z)"und danach der Befehlls -d §klistet alle nicht-komprimierte Dateien auf.
Mitunalias '§k'wird man dieses globale Alias wieder los. Wichtig hierbei sind die einfachen Anführungsstriche. Sonst wirkt nämlich §k weiter, was nicht im Sinne des Benutzers wäre.
- Aliase können seit Version 4.2 auch verwendet werden, um bestimmten Zeichenketten-Endungen nach einem Punkt automatisch mit dem selben Befehl aufzurufen, was meist für Datei-Endungen benutzt werden wird.
Dabei gilt:
alias -s NAME=WERT, wobei TEXT.NAME dann durch die Zsh zu WERT TEXT.NAME wird.
alias -s txt='less -rE'ruft alle ohne Befehl aufgerufenen Dateien automatisch mit dem Befehlless -rEauf, so dass man jetzt einfach nur den Dateinamen und ein return eingeben muss. Diese Funktionalität ist vergleichbar mit dem Anklicken einer oder mehrerer Dateien mit einem graphischen Dateimanager. Dabei kann man auch globale Zeichen wie*verwenden, also beispielsweise*.txtund ein "enter" eingeben um alle Dateien mit Endung ".txt" mit less zu lesen.
Praktischerweise gibt es mitautoload zsh-mime-setup ; zsh-mime-setupdie Möglichkeit, an Hand der Mime-Definitionen in /etc/ schon bestimmte Datei-Endungen mit bestimmten Programmen zu belegen.
alias -s de=w3mruft alle WWW-Seiten mit .de direkt mit w3m auf. (".de" in der Eingabe ist in diesem Fall keine Datei-Endung! )
- In der Zsh kann man aus jeder eigenen Funktion eine Datei machen, ohne dass diese Datei ausführbar sein muß. Hierzu setzt man die Variable FPATH bzw fpath (siehe unten) auf das oder die Verzeichnisse, die berücksichtigt werden sollen.
In der Datei genügt es, einfach eine oder mehrere Funktionen zu schreiben: z.B.begruessung() { echo "Hallo, $1" ; } herzlich() { echo "Ist ja riesig, $1, Dich zu sehen" ; }Jetzt muß noch dieser Dateiname mitautoloadbekannt gemacht werden. Daraufhin stehen nach einmaligem Aufruf des Namens der Funktionen die beiden Funktionen dann zur Verfügung. Schreibt man nur den Funktionsrumpf allein dann hat das gegenüber dem Schreiben von Funktionen den Vorteil, sofort ausgeführt werden zu können. autoload-Funktionen müssen nämlich erst einmal aufgerufen werden, damit ihr Rumpf bekannt ist.dateiname
Beispiel:echo "Ist das schön, $1, Dich zu sehen!" > .zsh/funktionen/begruessungist nach Aufruf vonautoload begruessungsofort nutzbar.
(siehe AUTOLOADING FUNCTIONS unter man zshmisc)- Statt in eine "Backslashitis" beim Aufschreiben von Skalar-Variablen mit viel Inhalt zu verfallen, z.b beim Definieren des Pfades, gibt es bei der Zsh die Möglichkeit, das kleinbuchstabige Gegenüber des großbuchstabigen Variablennamens als eines Arrays zu verwenden und sogar für eigene Variablen mit
typeset -Tein "Gegenüber" von einer Skalar-Variable zu einer Feld-Variable durch die Kleinschreibweise der Variablen zu erzielen.
Dieser Variante kann man dann ein Feld aus Werten, durch Leerzeichen getrennt oder durch Zeilenumbrüch , zuweisen:
Beispiel PATH:
alt:PATH=/usr/bin\ :/usr/local/bin/\ :/usr/sbin\ :/usr/local/sbin\ :/usr/X11R6/binDa die Zsh für Feldvariablen runde Klammern braucht, wenn nicht
zsh: path=( /usr/bin /usr/local/bin /usr/sbin /usr/local/sbin /usr/X11R6/bin )setopt shwordsplitgesetzt ist, sind die Worte in runde Klammern eingeschlossen.
Wer allerdings kompatibel zur Sh/Ksh/Bash programmieren muss/will, der muss diese optionsetopt shwordsplitsetzen.
- Der Zle d.i. der Zeileneditor der Zsh ist denen anderer Shells überlegen. Hier kann man fröhlich mehrere Zeilen schreiben und nach dem Aufruf mit RETURN separat einzelne Zeilen korrigieren. Man muß also nicht mehr immer einen externen Editor aufrufen.
Besonders nett dabei: Wo die Bash nur das Manövrieren wie in einer einzigen Zeile zuläßt, kann man bei der Zsh bequem mit dem Cursor über mehrere Zeilen navigieren wie in einem Editor.
Will man innerhalb mehrerer Zeilen editieren, dann muß man entweder mitbindkey "^Xp" push-line-or-editoder ähnlicher Tastenbelegung diesen Puffer in einen anderen Puffer kopieren oder aber nach einem Control-C erneut die Zeilen zurückholen.- Mittels zle -N kann man eigene sogenannte Widgets, das sind Editier-Funktionen, zle bekannt machen. In den Variablen LBUFFER und RBUFFER liegt die Kommandozeile links bzw. rechts des Cursors, die man so sehr einfach manipulieren kann. Beispiel:
klammer() { LBUFFER="\${$LBUFFER" ; RBUFFER="}$RBUFFER" }erzeugt eine Funktion klammer, die man mitbindkey '^g' klammerjetzt zuweisen kann an die Taste Control-G.
Noch ein Beispiel für ein User-Widget:wohin() { dirs -v print -n "Wohin? " read WOHIN cd +${WOHIN:=0} }
Jetzt muß mitzle -Nwohin als User-Widget deklariert werden. Anschließend kann mitbindkey '^Ww' wohindie definierte und deklarierte Editier-Funktion aufControl-Wwgelegt werden.
Zusätzlich kann man mitautoload zedsogar einen Editor, der in der Z Shell selber geschrieben ist, benutzen, der dann von seiner Voreinstellung oder durchbindkey -eEmacs-artig, bei Eingabe vonbindkey -vvi-artig funktioniert. Gesichert wird allerdings durchcontrol-x control-woder im Vicmd-Modus mitZZund mit dem Befehl control-c bricht man ab. Ruft man zed mit der Option -f oder als fned auf, kann man Funktionen editieren.
Als wohltuend empfinde ich bei einem Kommando des Zeileneditors das Kommando insert-last-word, das im Gegensatz zur Bash nicht immer das letzte Wort, sondern bei wiederholtem Aufruf das letzte Wort davor und so weiter aufruft. (siehe auchman zshzle)
- Die Zsh unterstützt wie ihr Vorbild -die Ksh- Koprozesse. Koprozesse sind eine Möglichkeit, an Parallelprozesse Daten zu übergeben und Daten zu empfangen. Diese Koprozesse werden allerdings mit coproc eingeleitet und nicht wie bei der Ksh mit
|&.
Mitprint -pund mit>&pals Umlenkung kann ich Daten an den Prozeß senden und mit read -p und<&pals Umlenkung Daten von diesem Prozeß auslesen. Beispiel:
coproc ed /tmp/notizen print -p "a" ls -l >&p print -p ".\nwq"schreibt in einen parallel laufenden Koprozess, den altehrwürdigen Ed, die Ausgabe vonls -lund speichert den Inhalt in der Datei /tmp/notizen ab und beendet ed.
Weitgehender als ein Coprozess ist das Einladen des zpty-Moduls mitzmodload zsh/zpty, welches dann ähnliche Steuerungsmöglichkeiten wie das Programm expect bietet. Als Beispiel für die Verwendung von zpty kann das Skript nslookup in /usr/share/zsh/4.x.x/functions/ dienen, was gleichnamiges interaktives Programm durch seine Vervollständigung leichter bedienbar macht.- Die Zsh kennt die Formatierungen, die die Ksh kennt. typeset -oben schon kurz bei assoziativen Variabelfeldern erwähnt- ist ein mächtiger Formatierbefehl der Ksh. Mit diesen Formatierungsregeln lassen sich Ausgaben auf unterschiedliche Weise formatieren.
typeset -L2 name=werteintrag ;print "[$name]"gibt linksformatiert "[we]" aus, die ersten 2 Buchstaben, umrahmt von [].
typeset -lL20 name=WERT;print "[$name]"gibt in Kleinbuchstaben (-l für lower) "[wert ]" aus, wobei 20 - 11 Leerzeichen eingefügt werden.
typeset -r RPROMPT=%nschützt den Rechtsprompt vor einem versehentlichen Überschreiben. Die Variable ist jetzt read-only und zsh warnt einen mit "zsh: read-only variable: RPROMPT ". Alle typeset-Befehle können mit einem-statt dem+aufgehoben werden.
(sieheman zshbuiltinsunter typeset ) Zusätzlich zutypesetkann man auch durch sogenannte Modifier die Ausgabe von
Beispiel:
name="Wert" print "[${(Ll:20:)name}]"ergibt genau die selbe Ausgabe wietypeset -lL20name.
Seit Zsh 4.1.1 kann man mitprintf "%20s\n" ${(L)a}ähnlich wie in der gleichnamigen C-Funktion auch dieses Ergebnis bekommen, ohne den externen printf-Befehl nutzen zu müssen.- Die Ausgabe von Dateinamen kann mittels sogenannter Qualifier spezifiziert werden:
(sieheman zshexpnunter Glob Qualifier)
z.B listetprint -l *(m-1)nur Dateien zeilenweise auf, die vor bis zu einem Tag modifiziert wurden.
print -l *(a1)listet Dateien zeilenweise auf, auf die vor einem Tag zugegriffen wurde.
print -l *(@)liste nur die Links zeilenweise auf.
ls -doF *(/)findet nur die Verzeichnisse.
chmod 640 *(W)verändert die Rechte aller Dateien, in die jeder schreiben darf, denn das ist ja besonders riskant!findet nur noch reine Dateien. Damit ist die unsinnige Meldung "grep: bla: Is a directory" für alle Zeiten vermeidbar.
grep name *(.)
Um einmal wieder an alte schlechtere Zeiten erinnert zu werden, könnte man auchgrep name *(^.@) eingeben.Hiermit werden alle Dateien aufgelistet, mit denen grep nichts anfangen kann, denn ^ ist das Nicht-Zeichen :).
gg() { grep -wE "$1" *(.) | less -r }könnte eine kleine Zsh-Funktion sein, um gezielt nach einem Wort und unter Zuhilfenahme von regulären Ausdrücken zu suchen. Ich persönlich benutze allerdings lieber perl für solche Dinge und habe dafür das Perl-Programmmgentdeckt.for i in [A-Z][A-Z]*(.); do mv $i ${i:l} ;doneist ein sehr schneller Befehl, um Dos-Dateien (keine Verzeichnise) zu Dateien mit kleinen Buchstaben zu machen. Der Qualifier :l (für lowercase) leistet hier ganze Arbeit.
print -l *(LM+3)gibt zeilenweise Dateien aus, die über 3 Megabyte groß sind.- Ich kann unter der Zsh komprimierte Email-Pakete lesen, ohne mich zuerst um das Entpacken kümmern zu müssen. Das geht bei gzip gepackten Dateien z.B. so:
mutt -f =(zcat mailfold*.gz)
In den =() steht dabei die Aktion, die mit einer Datei gemacht wird, es wird dabei eine temporäre Datei erzeugt und mit ihr z.B. mutt -f aufgerufen.
Ein anderes Beispiel:mutt -f =(grepmail "Mustafa Mustermann" ~/mbox)sucht alle Emails von Mustafa Mustermann aus einer sehr großen Email-Datei mbox mittelsgrepmail, einem sehr mächtigen Perl-Programm zum Herausfiltern von Emails, welche einem bestimmten Kriterium entsprechen, heraus. Die temporäre Datei wird selbstverständlich nachher wieder gelöscht.
mutt ist ein sehr schönes Mail-Programm, welches auch auf der Kommandozeile funktioniert, das ich empfehlen kann. Mit mutt -f liest mutt nicht aus /var/spool/mail, sondern die Email-Datei, hier mehrere Emaildateien.
Ein anderes Beispiel:lynxbzgrep() { lynx -force_html -dump =(bzip2 -cd $1 | grep $2) }ermöglicht es, mit lynxbz bzip2-gepackte HTML-Seiten nach einem Begriff zu untersuchen. Nötig wird dieser Mechanismus, wenn ein Programmlseekbenötigt. (sieheman 3 lseek)Wird keine temporäre Datei benötigt, dann kann man wie auch bei der Bash
<()verwenden. Damit erspart man sich dann die manuelle Verwendung von/proc/self/fdoder die manuelle Erzeugung einer "named pipe":lynx -force_html <( gzip -cd komprimiert.html.gz )ist ein Beispiel, bei dem lynx die Ausgabe vongzip -cd komprimiert.html.gzverarbeitet.
Durch intelligente Kommunikation verschiedener Prozeße wird es möglich, dass man zwei Pseudodateien erzeugen und miteinander vergleichen kann: In Shellkreisen wird dies als named pipe bezeichnet, die die Zsh indirekt erzeugt.diff <(zcat erste_datei.gz) <(zcat zweite_datei.gz)vergleicht den Inhalt zweiter komprimierter Dateien miteinander.- Nach Setzung von READNULLCMD=less läßt sich eine Datei mit
< dateiunter less angucken. Einfach ein<vor die Datei setzen.- Es ist ohne Probleme möglich, an mehrere Dateien die Standardausggabe umzulenken:
ls >datei1 >datei2 >datei3oder
ls >> datei1 >> datei2- Man kann auch die Standardeingabe von mehreren Dateien empfangen:
less < datei1 < datei2- Es ist möglich, eine Umlenkung in eine Datei und gleichzeitig an eine Pipe zu bewerkstelligen:
make >logfile | grep Error- Mit
ls -lL =emacskann ich beispielsweise in jedem Verzeichnis gucken, wie groß emacs genau ist. Ich muß nicht mehr den Pfad angeben. Die Zsh guckt für mich im Pfad nach, wenn ich emacs im Pfad habe. Ich kann auch beqüm Dateien, die im Pfad stehen, auf diese Art editieren.jed =genial.ceditiert eine C-Funktion, wenn sie im Pfad gefunden werden kann.- Statt eines sehr expliziten aber umständlich zu tippenden find-Befehls kann under der Zsh ** als rekursives Kürzel verwendet werden. Mit
print -l **/*.htmlfinde ich alle Html-Seiten, die in allen Verzeichnissen unterhalb des jetzigen Verzeichnisses vorhanden sind und gebe sie auf je einer Zeile (-l) aus.(**=Rekursion)
print -l **/datei.htmlsucht die bestimmte Datei in allen vom aktuellen Verzeichnis abgehenden Verzeichnissen und gibt genau sie aus.
print -l **/*.html~datei.htmlgibt alle Html-Seiten mit Ausnahme von datei.html zeilenweise aus.
grep name **/*.txtsucht in allen Texten unterhalb des gegenwärtigen Verzeichnisses nach Dateien mit Endung .txt.- Mit
vared Variablekann ich alle Umgebungsvariablen editieren. Das finde ich praktisch, weil ich sofort die Variable erreiche und nicht erst in einer Datei wie .zshrc nach ihr suchen muß. Außerdem wirkt natürlich das Editieren der Variablen sofort.- Der Befehl
dirs -vzeigt mir alle Verzeichnisse, in denen ich in einer Sitzung gewesen bin zeilenweise an, wenn ich wähle:
setopt autopushdIch kann nun mit cd +2 das vorletzte Verzeichnis erreichen.- Mit der Zsh kann ich sehr lange Unterverzeichnisse im Prompt mit einem kurzem oder signifikanteren Namen (named directory) versehen und dann mit ~name aufrufen. Das ist insbesondere dann sehr praktisch, wenn ich in einem sehr entfernten Ordner von / aus gesehen arbeite.
Ich habe mir eine kleine Zsh-funktion geschrieben ,die mir aus einem langem Verzeichnisnamen einen kurzen erzeugt:
zza () { NAMED_DIRECTORY=$PWD:t; # der Name des jetzigen Verzeichnisses wird # an NAMED_DIRECTORY ohne die Hierarchie übergeben. # :t steht für tail. eval $NAMED_DIRECTORY=$PWD; # es findet die Setzung eines named directory statt. cd ~$NAMED_DIRECTORY; # es wird in das named directory gesprungen. # ist mit dem bestehenden Verzeichnis identisch # aber der Name ist kürzer im Prompt. }
Eine außerdem sehr praktische Möglichkeit besteht darin, daß ich jetzt nicht mehr den ganzen Pfadnamen angeben muß, wenn ich eine Datei verschiebe. z.B.mv datei.1 ~lm1könnte meine Datei bequem nach /usr/local/man/man1/ verschieben, wenn ichlm1=/usr/local/man/man1gesetzt habe.
Bei der Prompt-Darstellung gibt es zwei Mölichkeiten: Entweder weißt man am Ende auch noch den letzten Slash zu:info=/usr/local/info/Dann wird im Prompt der ganze Name dargestellt.cd ~infospringt zwar nach /usr/local/info, aber im Prompt steht:/usr/local/info%. Möchte man aber den kurzen Prompt haben, dann muß man so zuweisen:
info=/usr/local/info, also ohne Slash am Ende.
- Die Option
autocderlaubt es, nur den Namen eines Ordners anzugeben. Bei Eindeutigkeit wird dann sofort in diesen Ordner gesprungen. z.B. springtbindann sofort in mein bin-Verzeichnis.- Es gibt keinen Fehler bei Farbprompts wie unter der Bash1-Shell. Da ich selber eine Gliederung meiner Promptinformationen durch Escape-Farbbefehle liebe, ist mir das wichtig.
Bei der Zsh müssen hierzu allerdings die Escape-Befehle von%{ %}eingerahmt werden. Also zum Beispiel:
%{^[[31m%}%~ %{[0m%}.
Ich habe mir, um die Übersicht nicht zu verlieren, Variablen definiert, die die Farben für den Prompt enthalten.RED_PROMPT='%{^[[31m%}' OFF_PROMPT='%{[0m%}'
Jetzt kann ich auf diese Variablen mit $ zugreifen.- Mit RPROMPT läßt sich ein PROMPT auf der rechten Seite definieren:
RPROMPT=%lzeigt mir beispielsweise an, auf welchem Rechner ich mich befinde.
RPROMPT=%nzeigt den Benutzer an.
RPROMPT=%Tzeigt die Zeit an.
RPROMPT=%D{%d.%m.%y}zeigt das Datum nach deutscher Dartstellung an.- Selbstverständlich kennt die Zsh auch eine Korrekturmöglichkeit bei falscher Eingabe, die aber nur dann wirksam wird, wenn man das wirklich eingestellt hat. Man setzt in einen solchem Fall einfach:
setopt autocorrect.
Die Korrektur kann durch Setzung einesalias <befehl>=nocorrect <befehl>verhindert werden.- Um darüber informatiert zu werden, wer alles außer mir sich eingeloggt hat gibt es die Feldvariable
watchwie unter der Tcsh.
watch=(notme)listet z.B alle Benutzer auf, die nicht ich sind :)
Hierbei kann das Format der Ausgabe geändert werde:
WATCHFMT='%n eingeloggt auf Terminal %l von %M seit %T '
Wählt manwatch=(@vorsicht_ist_angesagt), so werden alle Benutzer aufgeführt, die von dem Server vorsicht_ist_angesagt eingeloggt sind.
Positiv herum kann man so natürlich auch alle Freunde erkennen lassen:
watch=( < ~/.freunde root)liest alle Freunde aus der Datei.friendsin die Feldvariable watch zusätzlich zu root ein. So kann man schnell erkennen, wenn sich Freunde einloggen.
- Es gibt in der Zsh einen sehr bequemen Wiederholungsbefehl, der von der tcsh abgeschaut ist:
repeat. Möchte ich z.B. einen Werbemailer böswillig strafen, dann könnte ich das so machen:
repeat 100 mail -s "spams suck" badcompany@devilsheart.com < flameDabei sollte allerdings bedacht werden, daß man damit meist harmlose Benutzer trifft, die schlechte Passworte haben und deshalb Räubern auf den Leim gegangen sind.- Rufe ich ein altes Kommando mit
!?kommandoauf, habe ich die Möglichkeit, vor der erneuten Ausführung zu gucken, ob es sich hierbei auch um das gewünschte Kommando handelt. Ich drücke einfach TAB. Ebenso kann man sich auch die genau betroffenen Dateien eines global wirkenden Befehles (z.B. ls *.html) mit TAB ansehen.- Gerade eben getippte Worte auf der Kommandozeile können mit !# genauer wiedergegeben werden als bei Bash/Tcsh/Ksh. Man gibt einfach an, wo wiederholt werden soll: z.B.
echo ein_langes_wort zweites_langes_wort drei !#1-2schreibt auf den Bildschirm: ein_langes_wort zweites_langes_wort drei ein_langes_wort zweites_langes_wort.- periodic funct() PERIOD=300 fortune -s führt alle 300 Sekunden die Funktion funct aus und gibt eine Zeile vor dem Prompt einen kurzen Spruch weiter. Allerdings muß dazu auch am Prompt ein Befehl eingegeben werden, sonst kann man natürlich nichts auf dem Bildschirm sehen.
- Die Zsh kennt den .. Operator von Pascal (und Perl):
echo {1..7} "\nWo ist denn die Bash geblieben?"ergibt: 1 2 3 4 5 6 7 Wo ist denn die Bash geblieben?
- Die Zsh hat in ihrer sehr mächtigen HISTORY CONTROL ein run-help Kommando, mit dem zu einem Buffer gezielt Informationen abgerufen werden können. Voreingestellt ist hier der Aufruf der Manpage zu dem Kommando. Verändern könnte man diesen Aufruf, indem man einfach aus alias run-help=man
alias run-help=infomacht.man_zshall() man zshallund nachfolgendes Deklarieren vonzle -N man_zshallkann durch Definition vonbindkey '^g' man_zshallnun immer bei Control-G ausgeführt werden.schedist ein interner Befehl zum automatischen zeitgebundenen Abarbeiten von Kommandos ähnlich wie bei at. Dabei werden die Kommandos aber nicht ausgeführt und dann als email zugeschickt, sondern gelangen erst einmal in den Puffer und werden beim nächsten Kommando erst auf dem Bildschirm ausgegeben.sched +0:10 figlet "Du mußt jetzt los"führt in 10 Minuten in Großschrift auf dem Bildschirm eine Warnung zum Gehen aus. Dabei ist allerdings das Durchführen des Befehls abhängig von der Eingabe eines nächsten Befehls.
Z-Shell - Lokale Dokumentation
Copyright © 1997-2004: Wühlmaus FunProductions