Gostaria de adicionar uma maneira a $ PATH, em todo o sistema ou para um usuário individual, sem adicionar o mesmo caminho várias vezes.
Uma razão para querer fazer isso é para que as adições possam ser feitas .bashrc
, o que não requer login, e também é mais útil em sistemas que usam (por exemplo) lightdm
, que nunca chama .profile
.
Estou ciente das perguntas relacionadas à limpeza de duplicatas do $ PATH, mas não desejo remover duplicatas . Gostaria de adicionar caminhos apenas se eles ainda não estiverem presentes.
Respostas:
Suponha que o novo caminho que queremos adicionar seja:
Então, usando qualquer shell POSIX, podemos testar para ver se
new
já está no caminho e adicioná-lo se não estiver:Observe o uso de dois pontos. Sem os dois pontos, poderíamos pensar que, digamos,
new=/bin
já estava no caminho porque o padrão correspondia/usr/bin
. Enquanto os PATHs normalmente têm muitos elementos, os casos especiais de zero e um elemento no PATH também são tratados. O caso do caminho inicialmente não contendo elementos (sendo vazio) é tratada pela utilização de${PATH:=$new}
que cessionáriosPATH
para$new
se estiver vazia. Definir valores padrão para parâmetros dessa maneira é um recurso de todos os shells do POSIX: consulte a seção 2.6.2 dos documentos do POSIX .)Uma função que pode ser chamada
Por conveniência, o código acima pode ser colocado em uma função. Essa função pode ser definida na linha de comando ou, para disponibilizá-la permanentemente, ser inserida no script de inicialização do seu shell (para usuários do bash, seria
~/.bashrc
):Para usar esta função de atualização de caminho para adicionar um diretório ao PATH atual:
fonte
PATH
estiver vazio, isso adicionará uma entrada vazia (ou seja, o diretório atual) ao arquivoPATH
. Eu acho que você precisa de outro caso.case
. Apenas façacase "${PATH:=$new}"
. Veja minha própria resposta para fallbacks semelhantes.Crie um arquivo
/etc/profile.d
chamado, por exemplo,mypath.sh
(ou o que você quiser). Se você estiver usando o lightdm, verifique se é viável ou use/etc/bashrc
um arquivo originado do mesmo. Adicione a isso as seguintes funções:As coisas no início de (precedido por) $ PATH têm precedência sobre o que se segue e, inversamente, as coisas no final (em anexo) serão substituídas pelo que vem antes. Isso significa que se o seu $ PATH é
/usr/local/bin:/usr/bin
e existe um executávelgotcha
nos dois diretórios, aquele em/usr/local/bin
que será usado por padrão.Agora você pode - neste mesmo arquivo, em outro arquivo de configuração do shell ou na linha de comando - usar:
Se estiver em um
.bashrc
, impedirá que o valor apareça mais de uma vez quando você inicia um novo shell. Há uma limitação em que, se você quiser acrescentar algo que foi acrescentado (ou seja, mover um caminho dentro de $ PATH) ou vice-versa, precisará fazer isso sozinho.fonte
$PATH
comIFS=:
é, em última análise, mais flexível quecase
.case
IMO. Eu imagino queawk
poderia ser usado aqui também.gawk
poderia atribuir diretamente$PATH
.Você pode fazer assim:
Nota: se você criar PATH a partir de outras variáveis, verifique se elas não estão vazias, pois muitos shells interpretam "" como "". .
fonte
-q
é exigida pelo POSIX para grep, mas não sei se isso significa que ainda existem alguns greps (não POSIX) que não o possuem./my/bin
A parte importante do código é verificar se
PATH
contém um caminho específico:Ou seja, verifique se cada caminho
PATH
é delimitado em ambos os lados peloPATH
separador (:
) e, em seguida, verifique (-q
) se a string literal (-F
) que consiste em umPATH
separador, seu caminho e outroPATH
separador existe nele. Caso contrário, você pode adicionar o caminho com segurança:Isso deve ser compatível com POSIX e deve funcionar com qualquer caminho que não contenha um caractere de nova linha. É mais complexo se você deseja que ele trabalhe com caminhos contendo nova linha enquanto é compatível com POSIX, mas se você tiver um
grep
suporte,-z
poderá usá-lo.fonte
Eu tenho carregado essa pequena função comigo em vários
~/.profile
arquivos há anos. Eu acho que ele foi escrito pelo administrador do sistema em um laboratório Eu costumava trabalhar, mas não tenho certeza. De qualquer forma, é semelhante à abordagem de Goldilock, mas um pouco diferente:Portanto, para adicionar um novo diretório ao início do
PATH
:e até o fim:
fonte
/bin/grep
->grep
ATUALIZAR:
Notei que sua própria resposta tinha uma função separada para anexar ou anexar à
$PATH
. Gostei da ideia. Então eu adicionei um pouco de manipulação de argumentos. Eu também o coloquei no_
namespace corretamente :SAÍDA:
Por padrão, ele
-A
anexado a$PATH
, mas você pode alterar esse comportamento para-P
adicionar novamente em-P
qualquer lugar da sua lista de argumentos. Você pode voltar ao-A
pêndulo, entregando-o-A
novamente.AVALIAÇÃO SEGURA
Na maioria dos casos, recomendo que as pessoas evitem qualquer uso de
eval
. Mas acho que isso se destaca como um exemplo de seu uso para sempre. Nesse caso, a única instrução que vocêeval
pode ver éP=
ouA=
. Os valores de seus argumentos são rigorosamente testados antes de serem chamados. É para isso queeval
serve.Isto irá aceitar tantos argumentos como você dá-lo e adicionar cada um para
$PATH
apenas uma vez e somente se ele já não estiver no$PATH
. Ele usa apenas shell-script POSIX totalmente portátil, depende apenas de embutidos no shell e é muito rápido.fonte
_
prefixar funções de shell as torna "espaçadas corretamente"? Em outros idiomas, normalmente indica uma função global interna (ou seja, que precisa ser global, mas não se destina a ser usada externamente como parte de uma API). Meus nomes certamente não são ótimas opções, mas me parece que apenas o uso_
não resolve os problemas de colisão - seria melhor usar um espaço de nome real, por exemplo.mikeserv_path_assign()
._
, precisará trocar de gerenciador de pacotes. De qualquer forma, isso é essencialmente uma função "global, interna" - é global para todos os shell invocados no shell em que é declarado e é apenas um pouco de script de linguagem interpretada pendurado na memória do intérprete . unix.stackexchange.com/questions/120528/...unset a
(ou equivalente) no final do perfil?Contemplar! A função shell industrial de 12 linhas ... com capacidade industrial e zsh portátil que adora devotamente o seu script de inicialização
~/.bashrc
ou~/.zshrc
de escolha:Prepare-se para a glória instantânea. Então, ao invés de fazer isso e desejar o melhor:
Faça isso e tenha a garantia de obter o melhor, mesmo que você realmente queira ou não:
Muito bem, defina "Melhor".
Anexar e anexar com segurança à corrente
${PATH}
não é o assunto trivial que costuma ser feito. Embora convenientes e aparentemente sensatos, as linhas de uma linha do formulárioexport PATH=$PATH:~/opt/bin
convidam complicações diabólicas com:Nomes de diretório acidentalmente relativos (por exemplo,
export PATH=$PATH:opt/bin
). Enquantobash
ezsh
silenciosamente aceitar e principalmente ignorar dirnames relativas na maioria dos casos, dirnames relativos prefixado por qualquerh
out
(e possivelmente outros personagens nefastos) causa tanto para vergonhosamente se mutilam ala de Masaki Kobayashi seminal 1962 masterpiece Harakiri :Nomes de diretórios acidentalmente duplicados. Embora
${PATH}
nomes de diretórios duplicados sejam amplamente inócuos, eles também são indesejados, pesados, levemente ineficientes, impedem a depuração e promovem o desgaste da unidade - mais ou menos como esta resposta. Embora os SSDs do estilo NAND sejam (é claro ) imunes ao desgaste de leitura, os HDDs não são. O acesso desnecessário ao sistema de arquivos em cada comando tentado implica desgaste desnecessário da cabeça de leitura no mesmo ritmo. As duplicatas são particularmente untuosas ao invocar conchas aninhadas em subprocessos aninhados, nesse ponto aparentemente inofensivas como Não deixe isso acontecer com seus preciosos filhos. )export PATH=$PATH:~/wat
rapidamente explodem no Sétimo Círculo do${PATH}
InfernoPATH=/usr/local/bin:/usr/bin:/bin:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat:/home/leycec/wat
. Somente o Beelzebubba pode ajudá-lo se você anexar nomes de diretório adicionais a ele. (${PATH}
nomes de diretórios ausentes sejam amplamente inócuos, eles também são geralmente indesejados, pesados, levemente ineficientes, impedem a depuração e promovem o desgaste da unidade.Ergo, automação amigável como a função shell definida acima. Nós devemos nos salvar de nós mesmos.
Mas ... Por que "+ path.append ()"? Por que não simplesmente append_path ()?
Por desambigüidade (por exemplo, com comandos externos nas
${PATH}
funções de shell atuais ou em todo o sistema definidas em outro lugar), as funções de shell definidas pelo usuário são idealmente prefixadas ou com sufixo com substrings exclusivos suportados porbash
e, dezsh
outra forma, proibidos para nomes de bases de comando padrão - como, por exemplo+
,.Ei. Funciona. Não me julgue.
Mas ... Por que "+ path.append ()"? Por que não "+ path.prepend ()"?
Porque anexar à corrente
${PATH}
é mais seguro do que anexar à corrente${PATH}
, todas as coisas sendo iguais, o que nunca são. A substituição de comandos em todo o sistema por comandos específicos do usuário pode ser insalubre na melhor das hipóteses e loucura na pior. No Linux, por exemplo, os aplicativos downstream normalmente esperam as variantes de comandos do GNU coreutils , em vez de derivadas ou alternativas não padronizadas personalizadas.Dito isto, existem casos de uso válidos para isso. Definir a
+path.prepend()
função equivalente é trivial. Sans prolix nebulosity, por sua sanidade compartilhada:Mas ... Por que não Gilles?
A resposta aceita de Gilles em outros lugares é impressionantemente ótima no caso geral como um "anexo idempotente independente de shell" . No caso comum de
bash
ezsh
com não links simbólicos indesejáveis, no entanto, a pena de desempenho necessário para fazê-lo entristece o espremedor de Gentoo em mim. Mesmo na presença de links simbólicos indesejáveis, é discutível se bifurcar um subshell poradd_to_PATH()
argumento vale a inserção potencial de duplicatas simbólicos.Para casos de uso rigorosos que exigem a eliminação de duplicatas de links simbólicos, essa
zsh
variante específica faz isso por meio de componentes internos eficientes, em vez de garfos ineficientes:Observe o
*":${dirname:A}:"*
invés*":${dirname}:"*
do original.:A
é umzsh
ismo maravilhoso tristemente ausente na maioria das outras conchas - inclusivebash
. Para citarman zshexpn
:Sem mais perguntas.
De nada. Desfrute de bombardeios seguros. Agora você merece.
fonte
Aqui está minha versão no estilo de programação funcional.
*PATH
variável , não apenasPATH
.Também digno de nota:
export
ing; deixado para o chamador (veja exemplos)bash
; sem bifurcaçãofonte
Este script permite adicionar no final de
$PATH
:Ou adicione no início de
$PATH
:fonte