¿Puedo cambiar mi RUTA dinámicamente según mi cwd?

¿Puedo cambiar mi RUTA dinámicamente según mi cwd?

Me gustaría cambiar mi $PATHvariable de entorno dependiendo de mi directorio de trabajo actual.

Digamos que estoy dentro /foo/bar/bazy tengo los directorios /foo/node_modules/.biny /foo/bar/baz/node_modules/.bin. Me gustaría agregar todos los posibles ./node_modules/.binde forma recursiva $PATH.

Pero cuando entro cden un directorio diferente (como /foo/bar), quiero que $PATHse restaure mi original, limpio, y luego comenzar a buscar de ./node_modules/.binforma 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 $Xesté el $PWDo 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 .bashrcdeberí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_COMMANDvariable le permite especificar un comando que se ejecutará cada vez que se muestre el mensaje. Agregué una $PROMPT_COMMAND_OLDvariable para permitir $PROMPT_COMMANDrestaurar el original.

Probablemente no sea necesario, pero por buena forma agrego una $LAST_WDvariable y pruebo para evitar volver a calcular la ruta cuando el directorio no ha cambiado. Puede eliminar las tres líneas que contienen LAST_WDsi lo desea.

La augment_pathfunción escanea desde $PWDarriba, 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, PATHse cambia la variable. Se agrega un directorio adicional al final.

Si no hay ningún directorio ./node_modules/.binen 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 ~/.bashrchará lo que quieras.

Si la variable de entorno de bash PROMPT_COMMANDestá configurada para algún comando, ese comando se ejecuta antes de que bash muestre el mensaje principal.

En el código siguiente, PROMPT_COMMANDse 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 PATHen 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

información relacionada