Retirar entradas duplicadas da variável PATH

8

Eu modifico o meu .bashrc com freqüência e, em seguida, fonte-lo. No entanto, quando tenho coisas como export PATH="~/bin:~/perl5/bin:$PATH" no meu arquivo, então a variável de ambiente PATH cresce a cada vez que eu forneço o arquivo.

Por exemplo, na primeira vez em que .bashrc é originado, a variável PATH consiste em ~/bin:~/perl5/bin:/usr/bin:/bin .

A segunda vez que consiste em ~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/bin .

A terceira vez que consiste em ~/bin:~/perl5/bin:~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/bin .

Existe uma maneira simples de adicionar apenas algo que ainda não esteja no PATH?

    
por Christopher Bottoms 19.10.2010 / 16:43

6 respostas

12

Use a função pathmunge () disponível na maioria das distribuições /etc/profile :

pathmunge () {
if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
   if [ "$2" = "after" ] ; then
      PATH=$PATH:$1
   else
      PATH=$1:$PATH
   fi
fi
}

editar : para zsh usuários, typeset -U <variable_name> desduplicará as entradas de caminho.

    
por 19.10.2010 / 17:19
3

Eu estava com esse problema, então usei uma combinação de técnicas listadas em StackOverflow pergunta. O seguinte é o que eu usei para deduzir a variável PATH real que já tinha sido definida, desde que eu não queria modificar o script de base.

    tmppath=(${PATH// /@})
    array=(${tmppath//:/ })
    for i in "${array[@]//@/ }"
    do
        if ! [[ $PATH_NEW =~ "$i" ]]; then
            PATH_NEW="${PATH_NEW}$i:";
        fi
    done;
    PATH="${PATH_NEW%:}"
    export PATH
    unset PATH_NEW

Você poderia sempre otimizar isso um pouco mais, mas eu tinha um código extra no meu original para exibir o que estava acontecendo para garantir que estava configurando corretamente as variáveis. A outra coisa a notar é que eu executo o seguinte

  1. substitua qualquer caractere SPACE por um caractere @
  2. dividir a matriz
  3. percorre a matriz
  4. substitua qualquer caractere @ na string do elemento por um espaço

Isso é para garantir que eu possa manipular diretórios com espaços em (diretórios base do Samba com nomes de usuário do Active Directory podem ter espaços!)

    
por 24.01.2014 / 18:31
1

Defina seu caminho explicitamente.

    
por 19.10.2010 / 17:01
1

Apenas uma string:

for i in $(echo $PATH|tr ":" "\n"|sort|uniq);do PATH_NEW="${PATH_NEW}$i:";done;PATH="${PATH_NEW%:}"
    
por 19.10.2010 / 17:20
1

Posso pensar em duas maneiras diferentes de resolver isso. O primeiro deles, é iniciar o seu .bashrc com uma linha que define explicitamente o seu PATH base, dessa forma toda vez que você o fonte, ele é redefinido para a base antes de adicionar diretórios adicionais.

Por exemplo, adicione:

# Reset the PATH to prevent duplication and to make sure that we include
# everything we want.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Como alternativa, você pode verificar um item antes de adicioná-lo ao caminho. Para fazer isso, você usaria algo como:

if ! [[ $PATH =~ '~/perl5/bin' ]]
then
    PATH="~/perl5/bin:$PATH"
fi
O último tende a ficar um pouco repetitivo, se você está adicionando um monte de entradas, no entanto, eu costumo ficar com o primeiro. Se você quisesse usar isso e planejasse adicionar muitas entradas, escrever uma função bash para lidar com isso seria sensato.

Nota: A segunda opção pode funcionar apenas como está escrito nas versões modernas bash. O suporte à expressão regular não é um recurso do Bourne Shell (/ bin / sh) e pode não existir em outros shells. Além disso, o uso de citações pode não ser necessário ou pode até causar problemas em algumas versões mais recentes do bash.

    
por 19.10.2010 / 17:06
0

Aqui está a minha solução: PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}//")

Um bom forro simples que não deixa um rastro:

    
por 29.12.2014 / 08:14