Posso alterar o meu PATH dinamicamente com base no meu cwd?

4

Gostaria de alterar minha variável de ambiente $PATH , dependendo do meu diretório de trabalho atual.

Digamos que eu esteja em /foo/bar/baz e tenha os diretórios /foo/node_modules/.bin e /foo/bar/baz/node_modules/.bin . Gostaria de adicionar todos os possíveis ./node_modules/.bin recursivamente a $PATH .

Mas quando eu cd em um diretório diferente (como /foo/bar ), quero que meu $PATH original e limpo seja restaurado e, em seguida, comece a procurar novamente ./node_modules/.bin recursivamente.

(Eu quero resolver minha própria pergunta do rastreador de problemas do npm: Podemos adicionar pacotes instalados localmente ao PATH, também? )

Nota: estou em um Mac, mas estou interessado em uma solução geral.

    
por Pipo 13.05.2015 / 06:46

3 respostas

3

Introdução

Se eu entendi corretamente, você deseja adicionar diretórios "$X/node_modules/.bin" , em que $X é o $PWD ou qualquer um de seus ancestrais.

O script no final deste post deve dar o comportamento desejado. Você precisa fonte em todas as sessões onde você quer. Se você nomear o arquivo augment_path.sh , adicionar essa linha ao seu .bashrc deve ser suficiente:

source augment_path.sh

Discussão

Eu acho que o garyjohn tem a abordagem básica correta, mas ele está pesquisando todos os descendentes ao invés de todos os ancestrais.

A variável $PROMPT_COMMAND permite que você especifique um comando a ser executado toda vez que o prompt for exibido. Eu adicionei uma variável $PROMPT_COMMAND_OLD para permitir que o original $PROMPT_COMMAND seja restaurado

Provavelmente não é necessário, mas para uma boa forma eu adiciono uma variável $LAST_WD e testei para evitar recomputar o caminho quando o diretório não foi alterado. Você pode remover todas as três linhas contendo LAST_WD , se quiser.

A função augment_path varre de $PWD para cima, procurando os diretórios de destino em cada ancestral e adicionando qualquer um que encontrar ao caminho.

  • Eles são colocados no caminho na ordem, portanto, o diretório mais profundo terá precedência se houver algum conflito. Eu suponho que este é o comportamento desejado. Se não, mude

    PATH_ADDITION="$PATH_ADDITION:$resolved_target"
    

    para

    PATH_ADDITION="$resolved_target:$PATH_ADDITION"
    
  • No entanto, esses diretórios terão precedência sobre o restante do caminho. Se você quiser que o restante do caminho tenha precedência, altere:

    PATH="$PATH_ADDITION:$RAW_PATH"
    

    para

    PATH="$RAW_PATH:$PATH_ADDITION"
    

Script

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"
    
por 16.05.2015 / 10:23
1

Acho que colocar o seguinte em seu ~/.bashrc fará o que você deseja.

Se a variável de ambiente bash PROMPT_COMMAND estiver configurada para algum comando, esse comando será executado antes que o bash exiba o prompt principal.

No código abaixo, PROMPT_COMMAND é definido com o nome de uma função, doit . Essa função verifica se o diretório de trabalho atual foi alterado e, em caso afirmativo, define PATH como seu valor original e, em seguida, verifica a presença de um subdiretório denominado node_modules/.bin . Se esse subdiretório existir, a função anexará os nomes dele e todos os subdiretórios abaixo dele a PATH . %pr_e%

    
por 13.05.2015 / 08:24
0

Você pode trabalhar com PROMPT_COMMAND :

de bash
PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'

Esse comando é executado toda vez que o prompt é aprovado. Portanto, toda vez que um comando terminar, a variável PATH é alterada. Um diretório adicional é adicionado ao final.

Se não houver diretório ./node_modules/.bin no diretório de trabalho atual, o caminho será anexado de qualquer maneira. Mas isso não é um problema. Não é pesquisado através (porque não existe).

Veja a demonstração:

$ 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
    
por 13.05.2015 / 08:20