Uma maneira mais confortável de editar um $ PATH longo?

34

Eu quero adicionar, em ~ / .bashrc, alguns diretórios ao meu $ PATH.

Meu $ PATH é bastante longo, por isso é um pouco difícil ver quais diretórios ele contém e em que ordem.

Eu sei que posso modificar meu ~ / .bashrc para ser:

PATH=$PATH:/some/dir
PATH=$PATH:/another/dir:/yet/another
PATH=$PATH:/and/another
...

facilitaria a leitura. Mas eu queria saber se nos últimos anos o Bash adquiriu alguma sintaxe que torna mais fácil a especificação de um PATH longo. Por exemplo, estou fantasiando sobre uma sintaxe semelhante a:

PATH=:((
  /some/dir
  /another/dir
  /yet/another
  /and/another
  ...
))

Eu sei que essa sintaxe é inválida. Eu queria saber se há algo tão fácil. Existe?

    
por Niccolo M. 15.11.2015 / 14:37

6 respostas

25

Eu uso um conjunto de funções de conveniência para adicionar ou anexar um caminho a uma variável. As funções vêm no tarball de distribuição do Bash em um arquivo contrib chamado "pathfuncs".

  • add_path adicionará a entrada ao final da variável PATH
  • pre_path adicionará a entrada ao início da variável PATH
  • del_path removerá a entrada da variável PATH, onde quer que seja

Se você especificar uma variável como o segundo argumento, ela usará isso em vez de PATH.

Por conveniência, aqui estão elas:

# is $1 missing from $2 (or PATH) ?
no_path() {
    eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
  no_path $* || eval ${2:-PATH}='eval echo :'$'${2:-PATH}: |
    sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"'
}

Se você adicioná-los ao seu arquivo de inicialização bash, você pode adicionar ao seu PATH assim:

pre_path $HOME/bin
add_path /sbin
add_path /usr/sbin

Ou especifique uma variável diferente:

pre_path $HOME/man MANPATH
pre_path $HOME/share/man MANPATH
add_path /usr/local/man MANPATH
add_path /usr/share/man MANPATH

Eu uso esse método em meus arquivos rc colocando os pre_paths primeiro e add_paths em segundo lugar. Isso torna todas as minhas mudanças de caminho fáceis de entender em um piscar de olhos. Outro benefício é que as linhas são curtas o suficiente para que eu possa adicionar um comentário à direita de uma linha, se necessário.

E como estas são funções, você pode usá-las interativamente a partir da linha de comando, como dizendo add_path $(pwd) para adicionar o diretório atual ao caminho.

    
por 15.11.2015 / 22:16
11

OK, eu descobri a seguinte solução, que eu acho que é elegante (no que diz respeito à sintaxe do shell). Ele usa a sintaxe de matriz do Bash e também uma maneira simples de juntar elementos:

paths=(
  /some/dir
  /another/dir
  '/another/dir with spaces in it'
  /yet/another
  /and/another
  /end
)
paths_joined=$( IFS=: ; echo "${paths[*]}" )

PATH=$paths_joined:$PATH

ALERTA!

Acontece que essa solução tem um problema : ao contrário das soluções de @terdon e @Starfish, ele não verifica primeiro se os caminhos já estão no PATH. Então, como eu quero colocar este código em ~ / .bashrc (e não em ~ / .profile), os caminhos duplicados irão aparecer no PATH. Portanto, não use essa solução (a menos que você a insira em ~ / .profile (ou, melhor, ~ / .bash_profile, pois possui uma sintaxe específica para Bash)).

    
por 15.11.2015 / 16:51
4

Eu quero adicionar, em ~ / .bashrc, alguns diretórios ao meu $ PATH.

Eu uso o seguinte no Cygwin. Deve funcionar em outras versões do bash. Você pode remover o unset PATH do seu PATH (se você fizer isso, talvez precise descobrir como adicionar os : separadores corretamente).

Nota:

  • Uma vez, tive essa funcionalidade em uma função bash , mas a perdi depois de uma falha de disco.

No meu .bash_profile :

# Build up the path using the directories in ~/.path_elements
unset PATH
while read line; do 
  PATH="${PATH}$line"; 
done < ~/.path_elements

...

# Add current directory to path
export PATH=".:${PATH}"

Em ~/.path_elements :

/home/DavidPostill/bin:
/usr/local/bin:
/usr/bin:
/c/Windows/system32:
/c/Windows
    
por 15.11.2015 / 15:00
4

Eu uso a função abaixo no meu ~/.bashrc . É algo que recebi de um administrador de sistemas no meu antigo laboratório, mas não acho que ele tenha escrito. Basta adicionar essas linhas ao seu ~/.profile ou ~/.bashrc :

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

Isso tem várias vantagens:

  • Adicionar novos diretórios ao $PATH é trivial: pathmunge /foo/bar ;
  • Evita entradas duplicadas;
  • Você pode optar por adicionar uma nova entrada ao início ( pathmunge /foo/bar ou final ( pathmunge /foo/bar after) do $PATH .

O arquivo de inicialização do seu shell conteria algo como:

pathmunge /some/dir
pathmunge /another/dir
pathmunge '/another/dir with spaces in it'
pathmunge /yet/another
pathmunge /and/another
pathmunge /end
    
por 15.11.2015 / 20:26
1

Eu uso isso no meu .bashrc (e também meu .zshrc, já que eu normalmente uso zsh onde disponível em vez de bash). Concedido, ele requer que eu adicione diretórios manualmente, mas uma vantagem é que, ao atualizá-lo, posso continuar copiando-o para novos servidores e não me preocupar com o PATH em um novo servidor sendo criado com diretórios que não existem nele. / p>

##
## PATH
##
## Instead of just clobbering our PATH with directories that may
## not be appropriate for this server, try to be intelligent about what we add
##
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[ -d /cs/sbin ]                  && PATH=/cs/sbin:$PATH
[ -d /cs/bin ]                   && PATH=/cs/bin:$PATH
[ -d /usr/ucb ]                  && PATH=$PATH:/usr/ucb
[ -d /usr/ccs/bin ]              && PATH=$PATH:/usr/ccs/bin
[ -d /usr/local/ssl/bin ]        && PATH=$PATH:/usr/local/ssl/bin
[ -d /usr/krb5/bin ]             && PATH=$PATH:/usr/krb5/bin
[ -d /usr/krb5/sbin ]            && PATH=$PATH:/usr/krb5/sbin
[ -d /usr/kerberos/sbin ]        && PATH=$PATH:/usr/kerberos/sbin
[ -d /usr/kerberos/bin ]         && PATH=$PATH:/usr/kerberos/bin
[ -d /cs/local/jdk1.5.0/bin ]    && PATH=$PATH:/cs/local/jdk1.5.0/bin
[ -d /usr/java/jre1.5.0_02/bin ] && PATH=$PATH:/usr/java/jre1.5.0_02/man
[ -d /usr/java1.2/bin ]          && PATH=$PATH:/usr/java1.2/bin
[ -d /cs/local/perl5.8.0/bin ]   && PATH=$PATH:/cs/local/perl5.8.0/bin
[ -d /usr/perl5/bin ]            && PATH=$PATH:/usr/perl5/bin
[ -d /usr/X11R6/bin ]            && PATH=$PATH:/usr/X11R6/bin
[ -d /etc/X11 ]                  && PATH=$PATH:/etc/X11
[ -d /opt/sfw/bin ]              && PATH=$PATH:/opt/sfw/bin
[ -d /usr/local/apache/bin ]     && PATH=$PATH:/usr/local/apache/bin
[ -d /usr/apache/bin ]           && PATH=$PATH:/usr/apache/bin
[ -d /cs/admin/bin ]             && PATH=$PATH:/cs/admin/bin
[ -d /usr/openwin/bin ]          && PATH=$PATH:/usr/openwin/bin
[ -d /usr/xpg4/bin ]             && PATH=$PATH:/usr/xpg4/bin
[ -d /usr/dt/bin ]               && PATH=$PATH:/usr/dt/bin

Eu faço o mesmo pelo meu MANPATH:

##
## MANPATH
##
## Instead of just clobbering our MANPATH with directories that may
## not be appropriate for this server, try to be intelligent about what we add
##
MANPATH=/usr/local/man
[ -d /usr/share/man ]            && MANPATH=$MANPATH:/usr/share/man
[ -d /usr/local/share/man ]      && MANPATH=$MANPATH:/usr/local/share/man
[ -d /usr/man ]                  && MANPATH=$MANPATH:/usr/man
[ -d /cs/man ]                   && MANPATH=$MANPATH:/cs/man
[ -d /usr/krb5/man ]             && MANPATH=$MANPATH:/usr/krb5/man
[ -d /usr/kerberos/man ]         && MANPATH=$MANPATH:/usr/kerberos/man
[ -d /usr/local/ssl/man ]        && MANPATH=$MANPATH:/usr/local/ssl/man
[ -d /cs/local/jdk1.5.0/man ]    && MANPATH=$MANPATH:/cs/local/jdk1.5.0/man
[ -d /usr/java/jre1.5.0_02/man ] && MANPATH=$MANPATH:/usr/java/jre1.5.0_02/man
[ -d /usr/java1.2/man ]          && MANPATH=$MANPATH:/usr/java1.2/man
[ -d /usr/X11R6/man ]            && MANPATH=$MANPATH:/usr/X11R6/man
[ -d /usr/local/apache/man ]     && MANPATH=$MANPATH:/usr/local/apache/man
[ -d /usr/local/mysql/man ]      && MANPATH=$MANPATH:/usr/local/mysql/man
[ -d /cs/local/perl5.8.0/man ]   && MANPATH=$MANPATH:/cs/local/perl5.8.0/man
[ -d /usr/perl5/man ]            && MANPATH=$MANPATH:/usr/perl5/man
[ -d /usr/local/perl/man ]       && MANPATH=$MANPATH:/usr/local/perl/man
[ -d /usr/local/perl5.8.0/man ]  && MANPATH=$MANPATH:/usr/local/perl5.8.0/man
[ -d /usr/openwin/man ]          && MANPATH=$MANPATH:/usr/openwin/man

Além de ter um único arquivo que posso copiar para sistemas em ambientes diferentes sem medo de adicionar diretórios inexistentes ao PATH, essa abordagem também tem a vantagem de permitir que eu especifique a ordem em que os diretórios devem aparecer o caminho. Como a primeira linha de cada definição redefine completamente a variável PATH, posso atualizar meu .bashrc e fornecê-lo após a edição para que meu shell seja atualizado sem adicionar entradas duplicadas (que usei para experimentar há muito tempo quando comecei simplesmente com " $ PATH = $ PATH: / new / dir ". Isso garante que eu receba uma cópia limpa na ordem que desejo.

    
por 16.11.2015 / 17:45
-1

Existe um caminho fácil! Leia Funções da Shell e Variáveis de Caminho em Linux Journal , 01 de março de 2000 Por Stephen Collyer

As funções me permitem usar um novo tipo de dados no meu ambiente bash - a lista separada por dois pontos. Além do PATH, eu os uso para ajustar meu LOCATE_PATH, MANPATH e outros, e como um tipo de dados geral na programação bash. Aqui está como eu configurei meu PATH (usando as funções):

# Add my bin directory to $PATH at the beginning, so it overrides 
addpath -f -p PATH $HOME/bin

# For Raspberry Pi development (add at end)
addpath -b -p PATH ${HOME}/rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

# remove nonexistent directories from PATH
delpath -n -p PATH

# ensure PATH contains unique entries
uniqpath -p PATH

Como o link do Linux Journal é referido como "quebrado", eu coloquei as Funções do Caminho Bash em um arquivo .shar no link

    
por 15.11.2015 / 20:13