
Ich möchte meine $PATH
Umgebungsvariable abhängig von meinem aktuellen Arbeitsverzeichnis ändern.
Angenommen, ich bin in /foo/bar/baz
und habe die Verzeichnisse /foo/node_modules/.bin
und /foo/bar/baz/node_modules/.bin
. Ich möchte alle möglichen ./node_modules/.bin
rekursiv zu hinzufügen $PATH
.
Aber wenn ich cd
in ein anderes Verzeichnis (wie /foo/bar
) gehe, möchte ich mein ursprüngliches, sauberes Verzeichnis $PATH
wiederherstellen und dann ./node_modules/.bin
erneut mit der rekursiven Suche beginnen.
(Ich möchte meine eigene Frage aus dem Issue-Tracker von npm lösen:Können wir auch lokal installierte Pakete zu PATH hinzufügen?)
Hinweis: Ich verwende einen Mac, bin aber an einer allgemeinen Lösung interessiert.
Antwort1
Einführung
Wenn ich Sie richtig verstehe, möchten Sie alle Verzeichnisse hinzufügen, "$X/node_modules/.bin"
in denen $X
sich das $PWD
oder eines seiner Vorgänger befindet.
Das Skript am Ende dieses Beitrags sollte das gewünschte Verhalten liefern. Sie müssen es in jeder Sitzung, in der Sie es wünschen, als Quelle verwenden. Wenn Sie die Datei benennen , sollte es ausreichen, augment_path.sh
diese Zeile hinzuzufügen :.bashrc
source augment_path.sh
Diskussion
Ich denke, Garyjohn hat den grundsätzlichen Ansatz richtig, aber er durchsucht alle Nachkommen und nicht alle Vorfahren.
Mit der $PROMPT_COMMAND
Variable können Sie einen Befehl angeben, der jedes Mal ausgeführt werden soll, wenn die Eingabeaufforderung angezeigt wird. Ich habe eine $PROMPT_COMMAND_OLD
Variable hinzugefügt, mit der das Original $PROMPT_COMMAND
wiederhergestellt werden kann
Es ist wahrscheinlich nicht notwendig, aber der guten Form halber füge ich eine $LAST_WD
Variable hinzu und teste, um eine Neuberechnung des Pfads zu vermeiden, wenn sich das Verzeichnis nicht geändert hat. Sie können alle drei Zeilen entfernen, die enthalten, LAST_WD
wenn Sie möchten.
Die augment_path
Funktion scannt von $PWD
oben, sucht in jedem Vorgänger nach den Zielverzeichnissen und fügt alle gefundenen Verzeichnisse dem Pfad hinzu.
Sie werden in der Reihenfolge im Pfad platziert, so dass das tiefste Verzeichnis Vorrang hat, wenn es Konflikte gibt. Ich gehe davon aus, dass dies das gewünschte Verhalten ist. Wenn nicht, ändern Sie
PATH_ADDITION="$PATH_ADDITION:$resolved_target"
Zu
PATH_ADDITION="$resolved_target:$PATH_ADDITION"
Diese Verzeichnisse haben jedoch alle Vorrang vor dem Rest des Pfads. Wenn Sie möchten, dass der Rest des Pfads Vorrang hat, ändern Sie Folgendes:
PATH="$PATH_ADDITION:$RAW_PATH"
Zu
PATH="$RAW_PATH:$PATH_ADDITION"
Skript
RAW_PATH="$PATH"
LAST_WD=`pwd`
augment_path() {
target="node_modules/.bin"
if [ "$PWD" = "$LAST_WD" ]; then return 0; fi;
PATH_ADDITION=""
scandir="$PWD"
until [ "$scandir" = "" ]; do
resolved_target="$scandir"/"$target"
if [ -d "$resolved_target" ]; then
PATH_ADDITION="$PATH_ADDITION:$resolved_target"
fi
scandir="${scandir%/*}"
done
PATH="$PATH_ADDITION:$RAW_PATH"
LAST_WD=`pwd`
}
PROMPT_COMMAND_OLD="${PROMPT_COMMAND%; augment_path}"
PROMPT_COMMAND="$PROMPT_COMMAND_OLD; augment_path"
Antwort2
Sie können mit Bash's arbeitenPROMPT_COMMAND
:
PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
Dieser Befehl wird jedes Mal ausgeführt, wenn die Eingabeaufforderung angezeigt wird. Daher PATH
wird die Variable jedes Mal geändert, wenn ein Befehl beendet wird. Am Ende wird ein zusätzliches Verzeichnis hinzugefügt.
./node_modules/.bin
Wenn im aktuellen Arbeitsverzeichnis kein Verzeichnis vorhanden ist , wird der Pfad trotzdem angehängt. Das ist aber kein Problem. Es wird nicht danach gesucht (da es nicht existiert).
Sehen Sie sich die Demonstration an:
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/node_modules/.bin
$ cd test
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/test/node_modules/.bin
$ cd /etc/
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/etc/node_modules/.bin
Antwort3
Ich denke, wenn Sie das Folgende in Ihre Datei aufnehmen, ~/.bashrc
wird das erreicht, was Sie möchten.
Wenn die Umgebungsvariable von Bash PROMPT_COMMAND
auf einen bestimmten Befehl eingestellt ist, wird dieser Befehl ausgeführt, bevor Bash die primäre Eingabeaufforderung anzeigt.
Im folgenden Code PROMPT_COMMAND
wird auf den Namen einer Funktion gesetzt, doit
. Diese Funktion prüft, ob sich das aktuelle Arbeitsverzeichnis geändert hat. Wenn ja, wird es zunächst PATH
auf den ursprünglichen Wert gesetzt. Anschließend wird geprüft, ob ein Unterverzeichnis mit dem Namen node_modules/.bin
vorhanden ist. Wenn dieses Unterverzeichnis vorhanden ist, hängt die Funktion den Namen dieses Unterverzeichnisses und aller Unterverzeichnisse darunter an PATH
.
orig_path="$PATH"
prev_pwd=""
doit() {
if [ "$PWD" != "$prev_pwd" ]; then
PATH="$orig_path"
if [ -d "node_modules/.bin" ]; then
PATH="$PATH$(find $PWD/node_modules/.bin -type d -printf ':%p')"
# For POSIX compatibility (macOS or other), use:
# PATH="$PATH$(find $PWD/node_modules/.bin -type d -exec echo -n :{} \;)"
fi
prev_pwd="$PWD"
fi
}
PROMPT_COMMAND=doit