ti-enxame.com

Como adicionar corretamente um caminho ao PATH?

Gostaria de saber onde um novo caminho deve ser adicionado à variável de ambiente PATH. Eu sei que isso pode ser conseguido editando .bashrc (por exemplo), mas não está claro como fazer isso.

Por aqui:

export PATH=~/opt/bin:$PATH

ou isto?

export PATH=$PATH:~/opt/bin
994
Paolo

As coisas simples

PATH=$PATH:~/opt/bin

ou

PATH=~/opt/bin:$PATH

dependendo se você deseja adicionar ~/opt/bin no final (a ser pesquisado após todos os outros diretórios, caso exista um programa com o mesmo nome em vários diretórios) ou no início (a ser pesquisado antes de todos os outros diretórios).

Você pode adicionar várias entradas ao mesmo tempo. PATH=$PATH:~/opt/bin:~/opt/node/bin ou variações na encomenda funcionam muito bem. Não coloque export no início da linha, pois ela apresenta complicações adicionais (veja abaixo em "Notas sobre conchas que não sejam do bash").

Se o seu PATH for criado por muitos componentes diferentes, você poderá acabar com entradas duplicadas. Veja Como adicionar o caminho do diretório inicial a ser descoberto pelo Unix, qual comando? e Remova entradas duplicadas de $ PATH com o comando awk para evitar adicionar duplicatas ou removê-las.

Algumas distribuições colocam automaticamente ~/bin no seu PATH, se existir, a propósito.

Onde colocá-lo

Coloque a linha para modificar PATH em ~/.profile ou em ~/.bash_profile se é isso que você tem.

Observe que ~/.bash_rc não é lido por nenhum programa e ~/.bashrc é o arquivo de configuração de instâncias interativas do bash. Você não deve definir variáveis ​​de ambiente em ~/.bashrc. O lugar certo para definir variáveis ​​de ambiente como PATH é ~/.profile (ou ~/.bash_profile se você não se importa com conchas que não sejam o bash). Veja Qual é a diferença entre eles e qual devo usar?

Não coloque /etc/environment ou ~/.pam_environment: estes não são arquivos do Shell, você não pode usar substituições como $PATH lá. Nesses arquivos, você pode substituir apenas uma variável, não adicionar a ela.

Possíveis complicações em alguns scripts do sistema

Você não precisa de export se a variável já estiver no ambiente: qualquer alteração no valor da variável é refletida no ambiente.¹ PATH praticamente sempre está no ambiente; todos os sistemas unix definem isso muito cedo (geralmente no primeiro processo, de fato).

No momento do login, você pode confiar em que PATH já esteja no ambiente e já contenha alguns diretórios do sistema. Se você estiver escrevendo um script que pode ser executado mais cedo durante a configuração de algum tipo de ambiente virtual, pode ser necessário garantir que PATH não esteja vazio e seja exportado: se PATH ainda não estiver definido , então algo como PATH=$PATH:/some/directory definiria PATH como :/some/directory, e o componente vazio no início significa o diretório atual (como .:/some/directory).

if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi

Notas sobre conchas que não sejam o bash

No bash, ksh e zsh, export é uma sintaxe especial e os dois PATH=~/opt/bin:$PATH e export PATH=~/opt/bin:$PATH faça a coisa certa mesmo. Em outros shells no estilo Bourne/POSIX, como dash (que é /bin/sh em muitos sistemas), export é analisado como um comando comum, o que implica duas diferenças:

Então, em conchas como traço, export PATH=~/opt/bin:$PATH define PATH para a cadeia literal ~/opt/bin/: seguido pelo valor de PATH até o primeiro espaço. PATH=~/opt/bin:$PATH (uma tarefa simples) não requer aspas e faz a coisa certa. Se você quiser usar export em um script portátil, precisará escrever export PATH="$HOME/opt/bin:$PATH" ou PATH=~/opt/bin:$PATH; export PATH (ou PATH=$HOME/opt/bin:$PATH; export PATH pela portabilidade até do Bourne Shell que não aceitou export var=value e não fez expansão til).

¹ Isso não era verdade nos reservatórios Bourne (como no Bourne Shell atual, não nos reservatórios modernos do estilo POSIX), mas é altamente improvável que você encontre esses reservatórios antigos hoje em dia.

1114

De qualquer maneira, funciona, mas eles não fazem a mesma coisa: os elementos de PATH são marcados da esquerda para a direita. No seu primeiro exemplo, executáveis ​​em ~/opt/bin terá precedência sobre os instalados, por exemplo, em /usr/bin, que pode ou não ser o que você deseja.

Em particular, do ponto de vista da segurança, é perigoso adicionar caminhos à frente, porque se alguém puder obter acesso de gravação ao seu ~/opt/bin, eles podem colocar, por exemplo, um ls diferente, que você provavelmente usaria em vez de /bin/ls sem perceber. Agora imagine o mesmo para ssh ou seu navegador ou escolha ... (O mesmo vale três vezes para colocar. Em seu caminho.)

88
Ulrich Schwarz

Estou confuso com a pergunta 2 (desde que removida da pergunta por se tratar de um problema não relacionado):

O que é uma maneira viável de acrescentar mais caminhos em linhas diferentes? Inicialmente, pensei que isso poderia funcionar:

export PATH=$PATH:~/opt/bin
export PATH=$PATH:~/opt/node/bin

mas não porque a segunda tarefa não apenas anexa ~/opt/node/bin, mas também o todo PATH atribuído anteriormente.

Esta é uma solução possível:

export PATH=$PATH:~/opt/bin:~/opt/node/bin

mas, para facilitar a leitura, prefiro ter uma atribuição para um caminho.

Se você diz

PATH=~/opt/bin

isso é tudo que estará no seu CAMINHO. PATH é apenas uma variável de ambiente e, se você deseja adicionar ao PATH, precisa reconstruir a variável exatamente com o conteúdo que deseja. Ou seja, o que você dá como exemplo para a pergunta 2 é exatamente o que você quer fazer, a menos que eu esteja totalmente esquecido do ponto da questão.

Eu uso os dois formulários no meu código. Eu tenho um perfil genérico que eu instalo em todas as máquinas em que trabalho que se parece com isso, para acomodar os diretórios que potencialmente estão ausentes:

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done
39
Carl Cravens

O Linux determina o caminho da pesquisa executável com o $PATH variável de ambiente. Para adicionar o diretório/data/myscripts ao início do $PATH variável de ambiente, use o seguinte:

PATH=/data/myscripts:$PATH

Para adicionar esse diretório ao final do caminho, use o seguinte comando:

PATH=$PATH:/data/myscripts

Mas o anterior não é suficiente porque, quando você define uma variável de ambiente dentro de um script, essa alteração é efetiva apenas dentro do script. Existem apenas duas maneiras de contornar essa limitação:

  • Se dentro do script, você exportar a variável de ambiente, ela será eficaz em qualquer programa chamado pelo script. Observe que não é eficaz no programa que chamou o script.
  • Se o programa que chama o script faz isso por inclusão em vez de chamada, qualquer alteração no ambiente do script é efetiva no programa de chamada. Essa inclusão pode ser feita com o comando dot ou o comando source.

Exemplos:

$HOME/myscript.sh
source $HOME/myscript.sh

A inclusão basicamente incorpora o script "chamado" no script "chamado". É como um #include em C. Portanto, é eficaz dentro do script ou programa "chamado". Mas é claro que não é eficaz em nenhum programa ou script chamado pelo programa de chamada. Para torná-lo eficaz em toda a cadeia de chamadas, você deve seguir a configuração da variável de ambiente com um comando de exportação.

Como exemplo, o programa Shell do bash incorpora o conteúdo do arquivo .bash_profile por inclusão. Coloque as 2 linhas a seguir em .bash_profile:

PATH=$PATH:/data/myscripts
export PATH

efetivamente coloca essas duas linhas de código no programa bash. Portanto, no bash, a variável $ PATH inclui $HOME/myscript.sh e, devido à instrução de exportação, todos os programas chamados pelo bash têm a alteração $PATH variável. E como todos os programas executados a partir de um prompt do bash são chamados pelo bash, o novo caminho está em vigor para qualquer coisa que você execute a partir do prompt do bash.

A conclusão é que, para adicionar um novo diretório ao caminho, você deve anexar ou anexar o diretório à variável de ambiente $ PATH em um script incluído no Shell e exportar o $PATH variável de ambiente.

Mais informações aqui

25
Steve Brown

Já faz algum tempo que eu mantenho comigo duas funções pathadd e pathrm que ajudam a adicionar elementos ao caminho sem a necessidade de se preocupar com duplicações.

pathadd usa um argumento de caminho único e um argumento after opcional que, se fornecido, será anexado ao PATH, caso contrário, ele será anexado.

Em quase todas as situações, se você estiver adicionando ao caminho, provavelmente desejará substituir qualquer coisa que já esteja no caminho, e é por isso que opto por prefixar por padrão.

pathadd() {
    newelement=${1%/}
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$newelement"
        else
            PATH="$newelement:$PATH"
        fi
    fi
}

pathrm() {
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

Coloque-os em qualquer script que você deseja alterar o ambiente PATH e agora você pode fazer.

pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH

Você está garantido para não adicionar ao caminho, se ele já estiver lá. Se você deseja garantir agora /baz/bat está no início.

pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH

Agora, qualquer caminho pode ser movido para a frente, se já estiver no caminho sem dobrar.

20
Brett Ryan

Não posso falar por outras distribuições, mas o Ubuntu possui um arquivo/etc/environment, que é o caminho de pesquisa padrão para todos os usuários. Como meu computador é usado apenas por mim, coloquei todos os diretórios desejados no caminho, a menos que seja uma adição temporária que coloquei em um script.

10
Jim Bradley

Existem algumas situações em que ele usa PATH=/a/b:$PATH pode ser considerada a maneira "incorreta" de adicionar um caminho a PATH:

  1. Adicionando um caminho que não é realmente um diretório.
  2. Adicionando um caminho que já está em PATH no mesmo formulário.
  3. Adicionando um caminho relativo (já que o diretório atual pesquisado mudaria à medida que você altera o diretório de trabalho atual).
  4. Adicionando um caminho que já está em PATH em um formato diferente (ou seja, um alias devido ao uso de links simbólicos ou ..).
  5. Se você evitar fazer 4, não mova o caminho para a frente de PATH quando se pretende substituir outras entradas em PATH.

Essa função (somente Bash) faz a "coisa certa" nas situações acima (com uma exceção, veja abaixo), retorna códigos de erro e imprime mensagens agradáveis ​​para humanos. Os códigos e mensagens de erro podem ser desativados quando não são desejados.

prepath() {
    local usage="\
Usage: prepath [-f] [-n] [-q] DIR
  -f Force dir to front of path even if already in path
  -n Nonexistent dirs do not return error status
  -q Quiet mode"

    local tofront=false errcode=1 qecho=echo
    while true; do case "$1" in
        -f)     tofront=true;       shift;;
        -n)     errcode=0;          shift;;
        -q)     qecho=':';          shift;;
        *)      break;;
    esac; done
    # Bad params always produce message and error code
    [[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }

    [[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
    dir="$(command cd "$1"; pwd -P)"
    if [[ :$PATH: =~ :$dir: ]]; then
        $tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
        PATH="${PATH#$dir:}"        # remove if at start
        PATH="${PATH%:$dir}"        # remove if at end
        PATH="${PATH//:$dir:/:}"    # remove if in middle
    fi
    PATH="$dir:$PATH"
}

A exceção é que essa função não canoniza caminhos adicionados a PATH por outros meios, portanto, se um alias não canônico para um caminho estiver em PATH, isso adicionará uma duplicata. Tentar canonizar caminhos já em PATH é uma proposição arriscada, pois um caminho relativo tem um significado óbvio quando passado para prepath, mas quando já está no caminho, você não sabe qual era o diretório de trabalho atual. quando foi adicionado.

7
cjs

Para adicionar um novo caminho à variável de ambiente PATH:

export PATH=$PATH:/new-path/

Para que essa alteração seja aplicada a todos os Shell que você abrir, adicione-os ao arquivo que o Shell irá fonte quando for chamado. Em conchas diferentes, isso pode ser:

  • Bash Shell: ~/.bash_profile, ~/.bashrc ou perfil
  • Korn Shell: ~/.kshrc ou .profile
  • Shell Z: ~/.zshrc ou .zprofile

por exemplo.

# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH

Você pode ver o caminho fornecido na saída acima.

7
Amit24x7

Para mim (no Mac OS X 10.9.5), adicionar o nome do caminho (por exemplo, /mypathname) para o arquivo /etc/paths funcionou muito bem.

Antes de editar, echo $PATH retorna:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

Depois de editar /etc/paths e reiniciando o Shell, a variável $ PATH é anexada com /pathname. De fato, echo $PATH retorna:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

O que aconteceu é que /mypathname foi anexado ao $PATH variável.

6
faelx

Aqui está a minha solução:

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

Um forro fácil e agradável que não deixa um rastro :

5
AJ.