Als ich Ihre Frage las, war mein erster Gedanke $SHLVL
. Dann sah ich, dass Sie vim
Ebenen
zusätzlich zu Shell-Ebenen zählen wollten . Eine einfache Möglichkeit, dies zu tun, besteht darin, eine Shell-Funktion zu definieren:
vim() { ( ((SHLVL++)); command vim "$@");}
Dies wird bei SHLVL
jeder Eingabe eines vim
Befehls automatisch und unbeaufsichtigt inkrementiert . Sie müssen dies für jede Variante von vi
/ tun vim
, die Sie jemals verwenden. z.B,
vi() { ( ((SHLVL++)); command vi "$@");}
view() { ( ((SHLVL++)); command view "$@");}
Der äußere Satz von Klammern erstellt eine Subshell, sodass die manuelle Änderung des Werts von SHLVL
die aktuelle (übergeordnete) Shell-Umgebung nicht verschmutzt. Das command
Schlüsselwort soll natürlich verhindern, dass sich die Funktionen selbst aufrufen (was zu einer unendlichen Rekursionsschleife führen würde). Und natürlich sollten Sie diese Definitionen in Ihre .bashrc
oder eine andere Shell-Initialisierungsdatei einfügen.
Es gibt eine leichte Ineffizienz in der obigen. In einigen Muscheln (Bash ist eins), wenn Sie sagen
( cmd 1 ; cmd 2 ; … ; cmd n )
Wenn es sich um ein externes ausführbares Programm handelt (dh nicht um einen eingebauten Befehl), hält die Shell einen zusätzlichen Prozess herum, nur um auf das Beenden zu warten . Dies ist (wohl) nicht notwendig; Die Vor- und Nachteile sind umstritten. Wenn es Ihnen nichts ausmacht, ein wenig Speicher und einen Prozess-Slot zu belegen (und einen Shell-Prozess mehr zu sehen, als Sie benötigen, wenn Sie a ausführen ), gehen Sie wie oben beschrieben vor und fahren Sie mit dem nächsten Abschnitt fort. Das Gleiche gilt, wenn Sie eine Shell verwenden, bei der der zusätzliche Prozess nicht herumliegt. Wenn Sie jedoch den zusätzlichen Prozess vermeiden möchten, sollten Sie zunächst versuchen, dies zu tuncmdn
cmdn
ps
vim() { ( ((SHLVL++)); exec vim "$@");}
Der exec
Befehl soll verhindern, dass der zusätzliche Shell-Prozess nachlässt.
Aber es gibt ein GOTCHA. Die Bedienung der Shell SHLVL
ist etwas intuitiv: Beim Start der Shell wird geprüft, ob SHLVL
gesetzt ist. Wenn es nicht gesetzt ist (oder auf etwas anderes als eine Zahl gesetzt ist), setzt die Shell es auf 1. Wenn es gesetzt ist (auf eine Zahl), fügt die Shell 1 hinzu.
Aber von dieser Logik, wenn Sie sagen exec sh
, Ihr SHLVL
sollte steigen. Dies ist jedoch unerwünscht, da sich Ihr tatsächlicher Shell-Level nicht erhöht hat. Die Muschelgriffe dies durch eine Subtraktion von SHLVL
,
wenn Sie tun ein exec
:
$ echo "$SHLVL"
1
$ set | grep SHLVL
SHLVL=1
$ env | grep SHLVL
SHLVL=1
$ (env | grep SHLVL)
SHLVL=1
$ (env) | grep SHLVL
SHLVL=1
$ (exec env) | grep SHLVL
SHLVL=0
Damit
vim() { ( ((SHLVL++)); exec vim "$@");}
ist eine Wäsche; es wird SHLVL
nur inkrementiert , um es erneut zu dekrementieren. Sie können auch einfach sagen vim
, ohne eine Funktion zu nutzen.
Hinweis:
Laut Stéphane Chazelas (der alles weiß) sind einige Muscheln klug genug, dies nicht zu tun, wenn sie exec
sich in einer Unterschale befinden.
Um dies zu beheben, würden Sie tun
vim() { ( ((SHLVL+=2)); exec vim "$@");}
Dann habe ich gesehen, dass Sie vim
Ebenen
unabhängig von Shell-Ebenen zählen möchten. Nun, genau der gleiche Trick funktioniert (nun, mit einer kleinen Modifikation):
vim() { ( ((SHLVL++, VILVL++)); export VILVL; exec vim "$@");}
(und so weiter für vi
, view
usw.) Das export
ist notwendig, da VILVL
es standardmäßig nicht als Umgebungsvariable definiert ist. Es muss jedoch nicht Teil der Funktion sein. Sie können einfach export VILVL
als separates Kommando (in Ihrem .bashrc
) sagen . Und, wie oben beschrieben, wenn der zusätzliche Shell - Prozess für Sie kein Problem ist, können Sie tun , command vim
statt exec vim
, und lassen Sie SHLVL
allein:
vim() { ( ((VILVL++)); command vim "$@");}
Persönliche Präferenz:
Möglicherweise möchten Sie in VILVL
so etwas wie umbenennen VIM_LEVEL
. Wenn ich auf " VILVL
" schaue , schmerzen meine Augen; Sie können nicht sagen, ob es sich um eine falsche Schreibweise von „Vinyl“ oder eine falsch geformte römische Ziffer handelt.
Wenn Sie eine Shell verwenden, die nicht unterstützt wird SHLVL
(z. B. Bindestrich), können Sie sie selbst implementieren, solange die Shell eine Startdatei implementiert. Mach einfach so etwas wie
if [ "$SHELL_LEVEL" = "" ]
then
SHELL_LEVEL=1
else
SHELL_LEVEL=$(expr "$SHELL_LEVEL" + 1)
fi
export SHELL_LEVEL
in Ihrer .profile
oder einer entsprechenden Datei. (Sie sollten den Namen wahrscheinlich nicht verwenden SHLVL
, da dies zu Chaos führen kann, wenn Sie jemals eine unterstützte Shell verwenden SHLVL
.)
Andere Antworten haben das Problem der Einbettung von Umgebungsvariablenwerten in Ihre Shell-Eingabeaufforderung angesprochen, daher werde ich das nicht wiederholen, besonders wenn Sie sagen, dass Sie bereits wissen, wie es geht.
$SHLVL
Variable (die von mehreren Shells verwaltet wird) das, wonach Sie suchen?