
Me gustaría cambiar mi $PATH
variable de entorno dependiendo de mi directorio de trabajo actual.
Digamos que estoy dentro /foo/bar/baz
y tengo los directorios /foo/node_modules/.bin
y /foo/bar/baz/node_modules/.bin
. Me gustaría agregar todos los posibles ./node_modules/.bin
de forma recursiva $PATH
.
Pero cuando entro cd
en un directorio diferente (como /foo/bar
), quiero que $PATH
se restaure mi original, limpio, y luego comenzar a buscar de ./node_modules/.bin
forma recursiva nuevamente.
(Quiero resolver mi propia pregunta del rastreador de problemas de npm:¿Podemos agregar también paquetes instalados localmente a PATH?)
Nota: Estoy en una Mac, pero estoy interesado en una solución general.
Respuesta1
Introducción
Si te entiendo correctamente, deseas agregar cualquier directorio "$X/node_modules/.bin"
donde $X
esté el $PWD
o cualquiera de sus antepasados.
El script al final de esta publicación debería brindar el comportamiento que desea. Debe obtenerlo en cada sesión donde lo desee. Si le asigna al archivo el nombre augment_path.sh
, agregar esta línea a su .bashrc
debería ser suficiente:
source augment_path.sh
Discusión
Creo que Garyjohn tiene el enfoque básico correcto, pero está buscando en todos los descendientes en lugar de en todos los antepasados.
La $PROMPT_COMMAND
variable le permite especificar un comando que se ejecutará cada vez que se muestre el mensaje. Agregué una $PROMPT_COMMAND_OLD
variable para permitir $PROMPT_COMMAND
restaurar el original.
Probablemente no sea necesario, pero por buena forma agrego una $LAST_WD
variable y pruebo para evitar volver a calcular la ruta cuando el directorio no ha cambiado. Puede eliminar las tres líneas que contienen LAST_WD
si lo desea.
La augment_path
función escanea desde $PWD
arriba, busca los directorios de destino en cada ancestro y agrega los que encuentra a la ruta.
Se colocan en la ruta en orden, por lo que el directorio más profundo tendrá prioridad si hay algún conflicto. Supongo que este es el comportamiento deseado. Si no, cambia
PATH_ADDITION="$PATH_ADDITION:$resolved_target"
a
PATH_ADDITION="$resolved_target:$PATH_ADDITION"
Sin embargo, todos estos directorios tendrán prioridad sobre el resto de la ruta. Si desea que el resto de la ruta tenga prioridad, cambie:
PATH="$PATH_ADDITION:$RAW_PATH"
a
PATH="$RAW_PATH:$PATH_ADDITION"
Guion
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"
Respuesta2
Puedes trabajar con bashPROMPT_COMMAND
:
PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
Ese comando se ejecuta cada vez que aparece el mensaje. Por lo tanto, cada vez que finaliza un comando, PATH
se cambia la variable. Se agrega un directorio adicional al final.
Si no hay ningún directorio ./node_modules/.bin
en el directorio de trabajo actual, la ruta se agrega de todos modos. Pero eso no es un problema. No se busca (porque no existe).
Ver la demostración:
$ 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
Respuesta3
Creo que poner lo siguiente en tu ~/.bashrc
hará lo que quieras.
Si la variable de entorno de bash PROMPT_COMMAND
está configurada para algún comando, ese comando se ejecuta antes de que bash muestre el mensaje principal.
En el código siguiente, PROMPT_COMMAND
se establece el nombre de una función, doit
. Esa función verifica si el directorio de trabajo actual ha cambiado y, de ser así, primero lo establece PATH
en su valor original y luego verifica la presencia de un subdirectorio llamado node_modules/.bin
. Si ese subdirectorio existe, la función agrega sus nombres y todos los subdirectorios debajo de él 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