Removendo um diretório do PATH

18

Estou tentando compilar wxWidgets usando o MingW e tenho o cygwin no meu caminho, que parece estar em conflito. Então, eu gostaria de remover /d/Programme/cygwin/bin da variável PATH e gostaria de saber se existe alguma maneira elegante de fazer isso.

A abordagem ingênua seria fazer um eco em um arquivo, removê-lo manualmente e fornecê-lo, mas aposto que há uma abordagem melhor para isso.

    
por Devolus 11.01.2014 / 14:44

8 respostas

20

Não há ferramentas padrão para "editar" o valor de $ PATH (por exemplo, "adicionar pasta somente quando ela ainda não existe" ou "remover esta pasta"). Você acabou de executar:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

que seria para a sessão atual, se você quiser alterar permanentemente adicioná-lo a qualquer .bashrc, bash.bashrc, / etc / profile - o que melhor se adapta às suas necessidades de sistema e usuário. No entanto, se você estiver usando o BASH, você também pode fazer o seguinte se, digamos, quiser remover o diretório /home/wrong/dir/ da sua variável PATH, assumindo que está no final:

PATH=$(echo "$PATH" | sed -e 's/:\/home\/wrong\/dir$//')

Então, no seu caso, você pode usar

PATH=$(echo "$PATH" | sed -e 's/:\/d\/Programme\/cygwin\/bin$//')
    
por 11.01.2014 / 14:53
13

No bash:

directory_to_remove=/d/Programme/cygwin/bin
PATH=:$PATH:
PATH=${PATH//:$directory_to_remove:/:}
PATH=${PATH#:}; PATH=${PATH%:}

Se você não usar uma variável intermediária, precisará proteger os caracteres / no diretório a serem removidos para que não sejam tratados como o final do texto da pesquisa.

PATH=:$PATH:
PATH=${PATH//:\/d\/Programme\/cygwin\/bin:/:}
PATH=${PATH#:}; PATH=${PATH%:}

A primeira e a terceira linha estão disponíveis para organizar todos os componentes do caminho de pesquisa a serem rodeados por : , para evitar o uso especial do primeiro e último componente. A segunda linha remove o componente especificado.

    
por 12.01.2014 / 00:42
7

Depois de considerar outras opções apresentadas aqui e não entender completamente como algumas delas funcionavam, desenvolvi minha própria função path_remove , que adicionei ao meu .bashrc :

function path_remove {
  # Delete path by parts so we can never accidentally remove sub paths
  PATH=${PATH//":$1:"/":"} # delete any instances in the middle
  PATH=${PATH/#"$1:"/} # delete any instance at the beginning
  PATH=${PATH/%":$1"/} # delete any instance in the at the end
}

Isso acabou muito perto da solução de Gilles , mas envolvida como uma função básica que poderia ser facilmente usada na linha de comando.

Tem as vantagens de que, como uma função bash, funciona como um programa sem precisar ser um programa no caminho, e não requer nenhum programa externo para executar, apenas manipula a manipulação de strings.

Parece bastante robusto, em particular, ele não transforma somepath:mypath/mysubpath em somepath/mysubpath : se você executar path_remove mypath , que foi um problema que tive com minha função path_remove anterior.

Uma excelente explicação de como funciona a manipulação de string do bash pode ser encontrada no Guia avançado de script de script .

    
por 23.06.2016 / 13:34
3

Então, combinando as respostas de @gilles e @bruno-a (e um par de outros truques sed) eu criei este one-liner, que remove (a cada) REMOVE_PART do PATH, independentemente de ocorrer em o começo, meio ou fim do PATH

PATH=$(REMOVE_PART="/d/Programme/cygwin/bin" sh -c 'echo ":$PATH:" | sed "s@:$REMOVE_PART:@:@g;s@^:\(.*\):\$@@"')

É um pouco complicado, mas é bom poder fazer isso em apenas um hit. O ; é usado para unir os dois comandos separados do sed:

  • s@:$REMOVE_PART:@:@g (que substitui :$REMOVE_PART: por um único : )
  • s@^:\(.*\):\$@@ (que remove os dois pontos iniciais e finais que adicionamos com o comando echo)

E ao longo de linhas similares, eu apenas consegui criar este one-liner para adicionar um ADD_PART ao PATH, somente se o PATH ainda não o contiver

PATH=$(ADD_PART="/d/Programme/cygwin/bin" sh -c 'if echo ":$PATH:" | grep -q ":$ADD_PART:"; then echo "$PATH"; else echo "$ADD_PART:$PATH"; fi')

Altere a última parte para echo "$PATH:$ADD_PART" se você quiser adicionar ADD_PART ao final do PATH em vez de ao início.

...

... ou para tornar isso ainda mais fácil, crie um script chamado remove_path_part com o conteúdo

echo ":$PATH:" | sed "s@:$1:@:@g;s@^:\(.*\):\$@@"

e um script chamado prepend_path_part com o conteúdo

if echo ":$PATH:" | grep -q ":$1:"; then echo "$PATH"; else echo "$1:$PATH"; fi

e um script chamado append_path_part com o conteúdo

if echo ":$PATH:" | grep -q ":$1:"; then echo "$PATH"; else echo "$PATH:$1"; fi

torne-os todos executáveis e, em seguida, chame-os como:

  • PATH=$(remove_path_part /d/Programme/cygwin/bin)
  • PATH=$(prepend_path_part /d/Programme/cygwin/bin)
  • PATH=$(append_path_part /d/Programme/cygwin/bin)

Legal, mesmo se eu disser assim: -)

    
por 13.01.2015 / 04:56
2

É um exercício interessante escrever uma função bash para remover um diretório de uma variável de caminho.

Aqui estão algumas funções que eu uso em meus arquivos .bash * para acrescentar / adicionar diretórios a caminhos. Eles têm a virtude de remover entradas duplicadas, se houver, e trabalhar com qualquer tipo de variável de caminho separada por dois pontos (PATH, MANPATH, INFOPATH, ...). a função remove_from remove o diretório.

# {app,pre}pend_to path-var-name dirpath
# remove_from path-var-name dirpath
#
# Functions to manipulate a path-style variable.  {app,pre}pend_to
# both remove any other instances of dirname before adding it to
# the start or end of the path-var-name variable.
#
# Calling example:
#   append_to PATH "/usr/local/bin"
#
# Uses eval to allow target path varname to be passed in.
function remove_from() {
  # add surrounging colons
  eval tmp_path=":\$${1}:"
  # if dir is already there, remove it
  (echo "${tmp_path}" | grep --silent ":${2}:") &&
    tmp_path='echo "$tmp_path" | sed "s=:${2}:=:=g"'
  # remove surrounding colons
  tmp_path='echo "$tmp_path" | sed 's=^:==; s=:$==''
  eval export $1=\"$tmp_path\"
}
function append_to() {
  remove_from "$1" "$2"  # clean the path contents
  eval export $1=\"\$${1}:$2\"
}
function prepend_to() {
  remove_from "$1" "$2"  # clean the path contents
  eval export $1=\"${2}:\$$1\"
}
    
por 16.04.2015 / 22:26
1

Para completar / melhorar a resposta aceita de Tushar, você pode:

  • evite ter que escapar das barras no PATH usando delimitadores sem barra
  • omita a opção -e , conforme página de manual do sed : "Se não houver -e, --expression, -f, ou --file é dada, então o primeiro argumento não-opção é tomado como o script sed para interpretar. "
  • use o sinalizador g (global) para remover todas as ocorrências

No final, dá algo assim:

PATH=$(echo "$PATH" | sed 's@:/home/wrong/dir$@@g')
    
por 24.11.2014 / 11:54
1

Abaixo estão os códigos revisados da solução de Greg Tarsa. Apenas comandos de build-in bash são usados aqui. Assim, ele salvará muitas chamadas do sistema fork ().

# Calling example:
#   append_to PATH "/usr/local/bin"

function remove_from()
{
    local path="${1}"
    local dir="${2}"
    local -a dirs=()
    local old_ifs="${IFS}"
    IFS=":"
    set -- ${!path}
    while [ "$#" -gt "0" ]
    do
        [ "${1}" != "${dir}" ] && dirs+=("${1}")
        shift
        done
    eval "export ${path}=\"${dirs[*]}\""
    IFS="${old_ifs}"
}

function append_to()
{
    remove_from "${1}" "${2}"
    [ -d "${2}" ] || return
    if [ -n "${!1}" ]
    then
        eval "export ${1}=\"${!1}:${2}\""
    else
        eval "export ${1}=\"${2}\""
    fi
}

function prepend_to()
{
    remove_from "${1}" "${2}"
    [ -d "${2}" ] || return
    if [ -n "${!1}" ]
    then
        eval "export ${1}=\"${2}:${!1}\""
    else
        eval "export ${1}=\"${2}\""
    fi
}
    
por 02.11.2018 / 07:56
0

As respostas atuais não resolvem meu problema semelhante, pois preciso remover vários caminhos. Todos esses caminhos são subdiretórios de um único diretório. Nesse caso, este one-liner funciona para mim: (suponha que o padrão seja cygwin , ou seja, removendo todos os caminhos que contenham cygwin )

pattern=cygwin; export PATH=$(echo $PATH|tr ':' '\n'|sed "\#${pattern}#d" |tr '\n' ':')
    
por 07.09.2018 / 23:07