Como adicionar corretamente um caminho ao PATH?

787

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

Desta forma:

export PATH=~/opt/bin:$PATH

ou isso?

export PATH=$PATH:~/opt/bin
    
por Paolo 04.12.2011 / 21:57

11 respostas

872

O material simples

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

dependendo se você deseja adicionar ~/opt/bin no final (a ser pesquisado depois de todos os outros diretórios, caso haja 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 sobre o trabalho de encomenda muito bem. Não coloque export no início da linha, pois tem complicações adicionais (veja abaixo em "Nots on shells other than bash").

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

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

Onde colocar

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 local certo para definir variáveis de ambiente como PATH é ~/.profile (ou ~/.bash_profile se você não se importa com shells além de bash). Consulte Qual é a diferença entre eles e qual deles devo usar?

Não coloque isso em /etc/environment ou ~/.pam_environment : estes não são arquivos shell, você não pode usar substituições como $PATH lá. Nesses arquivos, você só pode substituir uma variável e não adicioná-la a ela.

Potenciais complicações em alguns scripts do sistema

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

No momento do login, você pode confiar em PATH já estar no ambiente e já conter alguns diretórios do sistema. Se você estiver escrevendo um script que pode ser executado no início enquanto configura algum tipo de ambiente virtual, talvez seja necessário garantir que PATH não esteja vazio e seja exportado: se PATH ainda não estiver definido, algo como PATH=$PATH:/some/directory definiria PATH para :/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 shells que não sejam bash

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

Em shells como dash, export PATH=~/opt/bin:$PATH define PATH para a string literal ~/opt/bin/: seguida do valor de PATH para o primeiro espaço. PATH=~/opt/bin:$PATH (uma tarefa nua) não requer cotações 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 para portabilidade até mesmo para o shell Bourne que não aceitou export var=value e não fez expansão do til).

¹ Isso não era verdade em shells Bourne (como no shell Bourne real, não em shells modernos no estilo POSIX), mas é altamente improvável que você encontre shells antigos nos dias de hoje.

    
por 05.12.2011 / 00:39
77

De qualquer forma, funciona, mas eles não fazem a mesma coisa: os elementos de PATH são verificados da esquerda para a direita. Em seu primeiro exemplo, os executáveis em ~/opt/bin terão precedência sobre aqueles 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 poderão colocar, por exemplo, um ls diferente nele , 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 triplamente para colocar em seu caminho.)

    
por 04.12.2011 / 22:09
32

Estou confuso com a pergunta 2 (já que foi removida da questão, já que foi devido a um problema não relacionado):

What's a workable way to append more paths on different lines? Initially I thought this could do the trick:

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

but it doesn't because the second assignment doesn't only append ~/opt/node/bin, but also the whole PATH previously assigned.

This is a possible workaround:

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

but for readability I'd prefer to have one assignment for one path.

Se você disser

PATH=~/opt/bin

que é all que estará no seu PATH. PATH é apenas uma variável de ambiente, e se você quiser adicionar ao PATH, você deve reconstruir a variável exatamente com o conteúdo que você 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 perdendo o ponto de vista da questão.

Eu uso os dois formulários no meu código. Eu tenho um perfil genérico que eu instalo em cada máquina que eu trabalho que se parece com isso, para acomodar possíveis diretórios em falta:

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
    
por 05.12.2011 / 01:25
23

O Linux determina o caminho de pesquisa executável com a variável de ambiente $PATH . Para adicionar diretório / data / myscripts ao início da variável de ambiente $PATH , 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 as precedentes não são suficientes porque, quando você define uma variável de ambiente dentro de um script, essa alteração é efetiva somente 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 todos os programas chamados pelo script. Note que não é eficaz dentro do programa que chamou o script.
  • Se o programa que chama o script fizer isso por inclusão, em vez de chamar, quaisquer alterações de ambiente no script serão efetivadas dentro do programa de chamada. Essa inclusão pode ser feita com o comando dot ou o comando de origem.

Exemplos:

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

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

Como exemplo, o programa bash shell incorpora o conteúdo do arquivo .bash_profile por inclusão. Então, colocando as duas linhas seguintes em .bash_profile:

PATH=$PATH:/data/myscripts
export PATH

efetivamente coloca essas duas linhas de código no programa bash. Portanto, dentro do bash, a variável $ PATH inclui $HOME/myscript.sh e, devido à declaração de exportação, qualquer programa chamado pelo bash tem a variável $PATH alterada. 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ê executar a partir do prompt do bash.

A linha inferior é que para adicionar um novo diretório ao caminho, você deve acrescentar ou preceder o diretório à variável de ambiente $ PATH dentro de um script incluído no shell, e você deve exportar a variável de ambiente $PATH . / p>

Mais informações aqui

    
por 05.12.2011 / 01:31
18

Há algum tempo que 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 tem um argumento de caminho único e um argumento after opcional que, se fornecido, será anexado ao PATH , caso contrário, será anexado a ele.

Em quase todas as situações, se você estiver adicionando o caminho, é provável que você queira substituir qualquer coisa que já esteja no caminho, e é por isso que eu prefiro 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%/}\(:\|\$\);;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

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

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

Você tem a garantia de não adicionar ao caminho se já estiver lá. Se você deseja garantir que /baz/bat esteja 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.

    
por 18.03.2016 / 00:28
15

A maneira à prova de balas de adicionar / pré-adicionar

Há muitas considerações envolvidas na escolha de acrescentar versus preceder. Muitos deles estão cobertos em outras respostas, então não vou repeti-los aqui.

Um ponto importante é que, mesmo que os scripts do sistema não usem isso (eu me pergunto por que) * 1 , a maneira à prova de balas para adicionar um caminho (por exemplo, $HOME/bin ) à variável de ambiente PATH é

PATH="${PATH:+${PATH}:}$HOME/bin"

para anexar (em vez de PATH="$PATH:$HOME/bin" ) e

PATH="$HOME/bin${PATH:+:${PATH}}"

para prepending (em vez de PATH="$HOME/bin:$PATH" )

Isso evita o cólon inicial / final espúrio quando $PATH está inicialmente vazio, o que pode ter efeitos colaterais indesejáveis e pode se tornar um pesadelo , difícil de encontrar (esta resposta lida brevemente com o caso do awk -way).

Explicação (de Expansão do Parâmetro da Shell ):

${parameter:+word}

If parameter is null or unset, nothing is substituted, otherwise the expansion of word is substituted.

Assim, ${PATH:+${PATH}:} é expandido para: 1) nada, se PATH for nulo ou não definido, 2) ${PATH}: , se PATH estiver definido.

Nota : isto é para o bash.

* 1 Acabei de descobrir que scripts como devtoolset-6/enable usam isso,
$ cat /opt/rh/devtoolset-6/enable
# General environment variables
export PATH=/opt/rh/devtoolset-6/root/usr/bin${PATH:+:${PATH}}
...
    
por 05.01.2018 / 17:36
9

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

    
por 07.02.2015 / 06:17
5

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

Antes de editar, echo $PATH retorna:

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

Após editar /etc/paths e reiniciar 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 à variável $PATH .

    
por 27.10.2015 / 16:01
5

Aqui está a minha solução:

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

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

    
por 29.12.2014 / 08:12
3

Existem algumas situações em que usar PATH=/a/b:$PATH pode ser considerado 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 real pesquisado mudaria à medida que você alterasse o diretório de trabalho atual).
  4. Adicionando um caminho que já está em PATH em um formato diferente (isto é, um alias devido ao uso de links simbólicos ou .. ).
  5. Se você evitar fazer 4, não moverá o caminho para a frente de PATH quando tiver a intenção de substituir outras entradas em PATH .

Esta função (Bash-only) faz a "coisa certa" nas situações acima (com uma exceção, veja abaixo), retorna códigos de erro e imprime boas mensagens 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. / p>     

por 02.11.2017 / 04:30
2

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 fornecerá quando for invocado. Em diferentes shells, isso pode ser:

  • Bash Shell: ~ / .bash_profile, ~ / .bashrc ou perfil
  • Korn Shell: ~ / .kshrc ou .profile
  • Z Shell: ~ / .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.

    
por 12.06.2017 / 12:47