
Gostaria de alterar minha $PATH
variável de ambiente dependendo do meu diretório de trabalho atual.
Digamos que estou dentro /foo/bar/baz
e tenho os diretórios /foo/node_modules/.bin
e /foo/bar/baz/node_modules/.bin
. Eu gostaria de adicionar todos os possíveis ./node_modules/.bin
recursivamente ao $PATH
.
Mas quando cd
entro em um diretório diferente (como /foo/bar
), quero que meu original limpo $PATH
seja restaurado e, em seguida, comece a procurar ./node_modules/.bin
recursivamente novamente.
(Quero resolver minha própria pergunta no rastreador de problemas do npm:Também podemos adicionar pacotes instalados localmente ao PATH?)
Nota: estou em um Mac, mas estou interessado em uma solução geral.
Responder1
Introdução
Se bem entendi, você deseja adicionar quaisquer diretórios "$X/node_modules/.bin"
onde $X
está o $PWD
ou qualquer um de seus ancestrais.
O script no final deste post deve fornecer o comportamento que você deseja. Você precisa obtê-lo em todas as sessões onde desejar. Se você nomear o arquivo augment_path.sh
, adicionar esta linha ao seu .bashrc
deverá ser suficiente:
source augment_path.sh
Discussão
Acho que garyjohn acertou a abordagem básica, mas ele está pesquisando todos os descendentes e não todos os ancestrais.
A $PROMPT_COMMAND
variável permite especificar um comando a ser executado cada vez que o prompt for exibido. Adicionei uma $PROMPT_COMMAND_OLD
variável para permitir que o original $PROMPT_COMMAND
seja restaurado
Provavelmente não é necessário, mas para uma boa forma, adiciono uma $LAST_WD
variável e testo para evitar recalcular o caminho quando o diretório não foi alterado. Você pode remover todas as três linhas que contêm, LAST_WD
se desejar.
A augment_path
função verifica de $PWD
cima para baixo, procurando os diretórios de destino em cada ancestral e adicionando ao caminho os que encontrar.
Eles são colocados no caminho em ordem, portanto, o diretório mais profundo terá precedência se houver algum conflito. Presumo que este seja o comportamento desejado. Se não, mude
PATH_ADDITION="$PATH_ADDITION:$resolved_target"
para
PATH_ADDITION="$resolved_target:$PATH_ADDITION"
No entanto, todos esses diretórios terão precedência sobre o resto do caminho. Se você quiser que o resto do caminho tenha precedência, altere:
PATH="$PATH_ADDITION:$RAW_PATH"
para
PATH="$RAW_PATH:$PATH_ADDITION"
Roteiro
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"
Responder2
Você pode trabalhar com bashPROMPT_COMMAND
:
PROMPT_COMMAND='[ -z "$X" ] && X=$PATH; PATH=$X:$(pwd)/node_modules/.bin'
Esse comando é executado sempre que o prompt aparece. Portanto, sempre que um comando termina, a PATH
variável é alterada. Um diretório adicional é adicionado ao final.
Se não houver nenhum 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 (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
Responder3
Acho que colocar o seguinte em sua ~/.bashrc
vontade fará o que você quiser.
Se a variável de ambiente bash PROMPT_COMMAND
estiver definida para algum comando, esse comando será executado antes que o bash exiba o prompt principal.
No código abaixo, PROMPT_COMMAND
está definido como o nome de uma função, doit
. Essa função verifica se o diretório de trabalho atual foi alterado e, em caso afirmativo, primeiro define PATH
seu valor original e, em seguida, verifica a presença de um subdiretório chamado node_modules/.bin
. Se esse subdiretório existir, a função anexa os nomes dele e de todos os subdiretórios abaixo dele a 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