PATH에서 디렉토리 제거


28

MingW를 사용하여 wxWidget을 컴파일하려고하는데 경로에 cygwin이 있는데 충돌하는 것 같습니다. 그래서 /d/Programme/cygwin/binPATH 변수에서 제거 하고 싶습니다.이를 수행하는 우아한 방법이 있는지 궁금합니다.

순진한 접근 방식은 파일에 파일을 에코하고 수동으로 제거하여 소싱하는 것이지만 더 나은 접근 방식이 있습니다.


2
많은 기술들이 여기에 나열되어 있습니다 : stackoverflow.com/questions/370047/…
slm

답변:


23

$ PATH의 값을 "편집"하는 표준 도구는 없습니다 (예 : "존재하지 않는 폴더 만 추가"또는 "이 폴더 제거"). 당신은 단지 실행 :

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

그것은 현재 세션을위한 것입니다. 만약 당신이 영구적으로 변경하고 싶다면 당신의 시스템과 사용자의 요구에 맞는 것을 .bashrc, bash.bashrc, / etc / profile에 영구적으로 추가하십시오. 그러나 BASH를 사용하는 경우 /home/wrong/dir/마지막에 있다고 가정하고 PATH 변수에서 디렉토리를 제거하려는 경우 다음을 수행 할 수도 있습니다 .

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

따라서 귀하의 경우에는

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

1
문제의 경로가 PATH 변수의 시작 부분에 있으면 끝에 콜론을 일치시켜야합니다. 이것은 PATH 변수의 쉬운 일반 조작을 복잡하게 만드는 성가신 경고입니다.
Graeme

4
많은 슬래시를 다룰 때 나는 정규식 구분 기호를 변경하는 것을 선호 /와 같은 뭔가 |: PATH=$(echo "$PATH" | sed -e 's|:/d/Programme/cygwin/bin$||')모든 탈출을 방지하기 위해.
Matthias Kuhn

17

bash에서 :

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

중간 변수를 사용하지 않는 경우 /검색 텍스트의 끝으로 처리되지 않도록 디렉토리 의 문자를 제거하여 제거해야합니다.

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

첫 번째와 세 번째 줄은 검색 경로의 모든 구성 요소가로 둘러싸여 정렬되도록 :하여 첫 번째와 마지막 구성 요소를 특수하게 묶지 않도록합니다. 두 번째 줄은 지정된 구성 요소를 제거합니다.


@Gilles에게 감사드립니다. 귀하의 답변에 따라 내 솔루션 을 제시하게되었으므로 4보다 PATH를 3 번만 조작하면됩니다. * 8 ')
Mark Booth

8

여기에 제시된 다른 옵션을 고려하고 그 중 일부가 어떻게 작동했는지 완전히 이해하지 못한 후 나는 내 자신의 path_remove기능을 개발했습니다 .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
}

이것은 Gilles의 솔루션과 거의 비슷 하지만 명령 줄에서 쉽게 사용할 수있는 bash 함수로 마무리되었습니다.

그것은 bash 함수로서 경로상의 프로그램 일 필요없이 프로그램처럼 작동하며 외부 프로그램을 실행할 필요없이 bash 문자열 조작만한다는 장점이 있습니다.

이 켜지지 않습니다 특히 그것은 매우 강력한 표시 somepath:mypath/mysubpathsomepath/mysubpath: 당신이 실행하는 경우 path_remove mypath내가 이전에했던 문제였다있는 path_remove기능.

bash 문자열 조작의 작동 방식에 대한 훌륭한 설명은 Advanced Bash-Scripting Guide를 참조하십시오 .


6

그래서 @gilles와 @ bruno-a (그리고 몇 가지 다른 sed tricks)의 대답을 결합 하여이 하나의 라이너를 생각해 냈습니다. PATH의 중간 또는 끝

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

조금 다루기 힘들지만 한 번에 할 수있는 것이 좋습니다. 은 ;함께 두 개의 분리 된 나오지도 명령을 결합하는 데 사용됩니다 :

  • s@:$REMOVE_PART:@:@g( :$REMOVE_PART:단일 대체 :)
  • s@^:\(.*\):\$@\1@ (이는 echo 명령으로 추가 한 선행 및 후행 콜론을 제거합니다)

그리고 비슷한 라인을 따라, 난 그냥 패스에 ADD_PART을 추가하기 위해이 한 줄을 마련하기 위해 관리했습니다 에만 경로가 이미 포함하지 않는 경우

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')

echo "$PATH:$ADD_PART"시작 대신 PATH 끝에 ADD_PART를 추가 하려면 마지막 부분을로 변경하십시오 .

...

... 또는이 작업을 더 쉽게 remove_path_part하려면 내용이 포함 된 스크립트를 작성하십시오.

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

prepend_path_part내용과 함께 호출 된 스크립트

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

append_path_part내용과 함께 호출 된 스크립트

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

그것들을 모두 실행 가능하게 만들고 다음과 같이 호출하십시오.

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

깔끔하게, 내가 그렇게 말하더라도 :-)


나는 제안, 특히 스크립트에 대한 아이디어를 좋아합니다.
Devolus

3

훨씬 더 간단한 하나의 라이너.

export PATH = 에코 $ PATH | tr ":" "\ n"| grep -v "anaconda"| tr "\ n" ":"`


2

경로 변수에서 디렉토리를 제거하기 위해 bash 함수를 작성하는 것은 흥미로운 연습입니다.

다음은 .bash * 파일에서 디렉토리를 경로에 추가 / 추가하기 위해 사용하는 일부 기능입니다. 중복 항목을 제거한다는 장점이 있으며 모든 종류의 콜론으로 구분 된 경로 변수 (PATH, MANPATH, INFOPATH 등)로 작업합니다. remove_from 함수는 디렉토리를 제거합니다.

# {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\"
}

2

아래는 Greg Tarsa의 솔루션에서 수정 된 코드입니다. 여기서는 bash 내장 명령 만 사용됩니다. 따라서 많은 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
}

1

Tushar에서 수락 된 답변을 완성 / 개선하기 위해 다음을 수행 할 수 있습니다.

  • 슬래시가 아닌 분리 문자를 사용하여 PATH에서 슬래시를 이스케이프하지 않아도됩니다.
  • sed 매뉴얼 페이지에 따라 -e옵션을 생략 하십시오 . "-e, --expression, -f 또는 --file 옵션이 없으면 첫 번째 비 옵션 인수가 해석 할 sed 스크립트로 사용됩니다."
  • g모든 항목을 제거 하려면 (global) 플래그를 사용하십시오.

결국, 그것은 다음과 같은 것을 제공합니다 :

PATH=$(echo "$PATH" | sed 's@:/home/wrong/dir$@@g')

0

현재 답변은 여러 경로를 제거해야한다는 점에서 비슷한 문제를 해결하지 못합니다. 이러한 모든 경로는 단일 디렉토리의 하위 디렉토리입니다. 이 경우,이 한 줄 나를 위해 작동합니다 (패턴은 가정 cygwin포함하는 모든 경로를 제거, 즉, cygwin)

pattern=cygwin; export PATH=$(echo $PATH|tr ':' '\n'|sed "\#${pattern}#d" |tr '\n' ':')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.